일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- 참조형변수
- 오라클
- 예외처리
- oracle
- 집합_SET
- 한국건설관리시스템
- cursor문
- GRANT VIEW
- 메소드오버로딩
- 자바
- 환경설정
- exception
- NestedFor
- abstract
- 제네릭
- 사용자예외클래스생성
- Java
- 생성자오버로드
- 대덕인재개발원
- 예외미루기
- 추상메서드
- 컬렉션 타입
- 객체 비교
- 다형성
- 자동차수리시스템
- EnhancedFor
- 인터페이스
- 정수형타입
- 어윈 사용법
- 컬렉션프레임워크
- Today
- Total
거니의 velog
(16) 컴포넌트 반복 2 본문
4. 응용
* 지금까지 배운 개념을 응용하여 고정된 배열을 리렌더링하는 것이 아닌, 동적인 배열을 렌더링하는 것을 구현해 보자. 그리고 index 값을 key로 사용하면 리렌더링이 비효율적이라고 배웠는데, 이러한 상황에서 어떻게 고윳값을 만들 수 있는지도 알아보자. 이 절의 실습 흐름은 다음과 같다.
(1) 초기 상태 설정하기
* IterationSample 컴포넌트에서 useState를 사용하여 상태를 설정해 보자. 세 가지 상태를 사용할 텐데 하나는 데이터 배열이고, 다른 하나는 텍스트를 입력할 수 있는 input의 상태이다. 그럼 마지막 하나는 무엇일까? 그것은 데이터 배열에서 새로운 항목을 추가할 때 사용할 고유 id를 위한 상태이다.
* 배열을 설정할 때, 조금 전에는 단순히 문자열로 이루어진 배열을 만들었지만, 이번에는 객체 형태로 이루어진 배열을 만들어 보자. 해당 객체에는 문자열과 고유 id 값이 있다.
* IterationSample 컴포넌트를 다음과 같이 수정해 보자.
import React, { useState } from 'react';
const IterationSample = () => {
const [names, setNames] = useState([
{ id: 1, text: '눈사람' },
{ id: 2, text: '얼음' },
{ id: 3, text: '눈' },
{ id: 4, text: '바람' },
]);
const [inputText, setInputText] = useState('');
const [nextId, setNextId] = useState(5); // 새로운 항목을 추가할 때 사용할 id
const namesList = names.map((name) => <li key={name.id}>{name.text}</li>);
return <ul>{namesList}</ul>;
};
export default IterationSample;
* 이번에는 map 함수를 사용할 때 key 값을 index 대신 name.id 값으로 지정해 주었다.
* 코드를 저장하고, 브라우저에서 이전과 같은 결과가 나타나는지 확인해 보자.
(2) 데이터 추가 기능 구현하기
* 이제 새로운 이름을 등록할 수 있는 기능을 구현해 보자.
* 우선 ul 태그의 상단에 input과 button을 렌더링하고, input의 상태를 관리해 보자.
import React, { useState } from 'react';
const IterationSample = () => {
const [names, setNames] = useState([
{ id: 1, text: '눈사람' },
{ id: 2, text: '얼음' },
{ id: 3, text: '눈' },
{ id: 4, text: '바람' },
]);
const [inputText, setInputText] = useState('');
const [nextId, setNextId] = useState(5); // 새로운 항목을 추가할 때 사용할 id
const onChange = (e) => setInputText(e.target.value);
const namesList = names.map((name) => <li key={name.id}>{name.text}</li>);
return (
<>
<input value={inputText} onChange={onChange} />
<button>추가</button>
<ul>{namesList}</ul>
</>
);
};
export default IterationSample;
* 그 다음에는 버튼을 클릭했을 때 호출할 onClick 함수를 선언하여 버튼의 onClick 이벤트로 설정해 보자.
* onClick 함수에서는 배열의 내장 함수 concat을 사용하여 새로운 항목을 추가한 배열을 만들고, setNames를 통해 상태를 업데이트해 준다.
import React, { useState } from 'react';
const IterationSample = () => {
const [names, setNames] = useState([
{ id: 1, text: '눈사람' },
{ id: 2, text: '얼음' },
{ id: 3, text: '눈' },
{ id: 4, text: '바람' },
]);
const [inputText, setInputText] = useState('');
const [nextId, setNextId] = useState(5); // 새로운 항목을 추가할 때 사용할 id
const onChange = (e) => setInputText(e.target.value);
const onClick = () => {
const nextNames = names.concat({
id: nextId, // nextId 값을 id로 설정하고
text: inputText,
});
setNextId(nextId + 1); // nextId 값에 1을 더해 준다.
setNames(nextNames); // names 값을 업데이트한다.
setInputText(''); // inputText를 비운다.
};
const namesList = names.map((name) => <li key={name.id}>{name.text}</li>);
return (
<>
<input value={inputText} onChange={onChange} />
<button onClick={onClick}>추가</button>
<ul>{namesList}</ul>
</>
);
};
export default IterationSample;
* 배열에 새 항목을 추가할 때 배열의 push 함수를 사용하지 않고 concat을 사용했는데, push 함수는 기존 배열 자체를 변경해 주는 반면, concat은 새로운 배열을 만들어 준다는 차이점이 있다.
* 리액트에서 상태를 업데이트할 때는 기존 상태를 그대로 두면서 새로운 값을 상태로 설정해야 한다. 이를 불변성 유지라고 하는데, 불변성 유지를 해 주어야 나중에 리액트 컴포넌트의 성능을 최적화할 수 있다. 이에 대한 자세한 내용은 추후에 알아보도록 하자.
* onClick 함수에서 새로운 항목을 추가할 때 객체의 id 값은 nextId를 사용하도록 하고 클릭될 때마다 값이 1씩 올라가도록 구현했다. 추가로 button이 클릭될 때 기존의 input 내용을 비우는 것도 구현해 주었다.
* 코드를 다 작성했다면 파일을 저장하고 브라우저를 열어서 새로운 항목을 추가해 보자.
(3) 데이터 제거 기능 구현하기
* 이번에는 각 항목을 더블클릭했을 때 해당 항목이 화면에서 사라지는 기능을 구현해 보자. 이번에도 마찬가지로 불변성을 유지하면서 업데이트 해 주어야 한다. 불변성을 유지하면서 배열의 특정 항목을 지울 때는 배열의 내장 함수 filter를 사용한다.
* filter 함수를 사용하면 배열의 특정 조건을 만족하는 원소들만 쉽게 분류할 수 있다. 사용 예시를 한 번 보자.
const numbers = [1, 2, 3, 4, 5, 6];
const biggerThanThree = numbers.filter(number => number > 3);
console.log(biggerThanThree);
* filter 함수의 인자에 분류하고 싶은 조건을 반환하는 함수를 넣어주면 쉽게 분류할 수 있다.
* 이 filter 함수를 응용하여 특정 배열에서 특정 원소만 제외시킬 수도 있다. 예를 들어 위 코드에서 본 numbers 배열에서 3만 없애고 싶다면 다음과 같이 하면 된다.
* 이제 filter 함수를 사용하여 IterationSample 컴포넌트의 항목 제거 기능을 구현해 보자. HTML 요소를 더블클릭할 때 사용하는 이벤트 이름은 onDoubleClick이다. onRemove라는 함수를 만들어서 각 li 요소에 이벤트 등록을 해 주자.
import React, { useState } from 'react';
const IterationSample = () => {
const [names, setNames] = useState([
{ id: 1, text: '눈사람' },
{ id: 2, text: '얼음' },
{ id: 3, text: '눈' },
{ id: 4, text: '바람' },
]);
const [inputText, setInputText] = useState('');
const [nextId, setNextId] = useState(5); // 새로운 항목을 추가할 때 사용할 id
const onChange = (e) => setInputText(e.target.value);
const onClick = () => {
const nextNames = names.concat({
id: nextId, // nextId 값을 id로 설정하고
text: inputText,
});
setNextId(nextId + 1); // nextId 값에 1을 더해 준다.
setNames(nextNames); // names 값을 업데이트한다.
setInputText(''); // inputText를 비운다.
};
const onRemove = (id) => {
const nextNames = names.filter((name) => name.id !== id);
setNames(nextNames);
};
const namesList = names.map((name) => (
<li key={name.id} onDoubleClick={() => onRemove(name.id)}>
{name.text}
</li>
));
return (
<>
<input value={inputText} onChange={onChange} />
<button onClick={onClick}>추가</button>
<ul>{namesList}</ul>
</>
);
};
export default IterationSample;
* 코드를 저장하고 브라우저에서 항목을 더블클릭하여 제거해 보자. 잘 지워지는가?
5. 정리
* 이 장에서는 반복되는 데이터를 렌더링하는 방법을 배우고, 이를 응용하여 유동적인 배열을 다루어 보았다. 컴포넌트 배열을 렌더링할 때는 key 값 설정에 항상 주의해야 한다. 또 key 값은 언제나 유일해야 한다. key 값이 중복된다면 렌더링 과정에서 오류가 발생한다.
* 상태 안에서 배열을 변형할 때는 배열에 직접 접근하여 수정하는 것이 아니라 concat, filter 등의 배열 내장 함수를 사용하여 새로운 배열을 만든 후 이를 새로운 상태로 설정해 주어야 한다는 것을 명심하자. 우리는 더욱 다양한 배열 및 객체 업데이트 방법들을 계속 배워 나갈 것이다.
'React_리액트 시작' 카테고리의 다른 글
(18) 컴포넌트의 라이프사이클 메서드 2 (1) | 2023.12.04 |
---|---|
(17) 컴포넌트의 라이프사이클 메서드 1 (0) | 2023.12.04 |
(15) 컴포넌트 반복 1 (0) | 2023.12.01 |
(14) ref:DOM 에 이름 달기 2 (0) | 2023.11.30 |
(13) ref:DOM 에 이름 달기 1 (0) | 2023.11.30 |