React Study(5) - 리액트를 다루는 기술 6장
#6장 컴포넌트 반복
웹 애플리케이션을 만들다 보면 다음과 같이 반복되는 코드를 작성할 때가 있습니다.
이 장에서는 리액트 프로젝트에서 반복적인 내용을 효율적으로 보여 주고 관리하는 방법을 알아봅니다.
<IterationSample.js>
const IterationSample = () => {
return (
<ul>
<li>눈사람</li>
<li>얼음</li>
<li>눈</li>
<li>사람</li>
</ul>
)
}
export default IterationSample;
6.1 자바스크립트 배열의 map()함수
map 함수를 사용하여 반복되는 컴포넌트를 렌더링할 수 있다
6.1.1 문법
arr.map(callback,[thisArg])의 파라미터
callback : 새로운 배열의 요소를 생성하는 함수로 파라미터는 다음 세 가지이다.
currentValue : 현재 처리하고 있는 요소
index : 현재 처리하고 있는 요소의 index값
array : 현재 처리하고 있는 원본 배열
thisArg : callback 함수 내부에서 사용할 this 레퍼런스
const numbers = [1,2,3,4,5];
const result = numbers.map(num=> num*num);
console.log(result)
6.2 데이터 배열을 컴포넌트 배열로 변환하기
배열로 컴포넌트로 구성된 배열을 생성할 수도 있다.
6.2.1 컴포넌트 구성하기
<IterationSample.js>
const IterationSample = () => {
const names = ['눈사람','얼음','눈','바람'];
const nameList = names.map(name=> <li>{name}</li>);
return <ul>{nameList}</ul>
}
export default IterationSample;
하지만 "key" prop이 없다고 경고 메시지를 표시한다.
6.4 key
리액트에서 key는 컴포넌트 배열을 렌더링했을 때 어떤 원소에 변동이 있었는지 알아내려고 사용합니다.
예를 들어 유동적인 데이터를 다룰 때는 원소를 새로 생성할 수도 제거할 수도 수정할 수도 있다.
key가 없을 때는 Virtual DOM을 비교하는 과정에서 리스트를 순차적으로 비교하면서 감지한다.
하지만 key가 있다면 이 값을 사용하여 어떤 변화가 일어났는지 더욱 빠르게 알아낼 수 있다.
6.3.1 key 설정
key값을 설정할 때는 map 함수의 인자로 전달되는 함수 내부에서 컴포넌트 props를 설정하듯이 설정하면 됩니다.
key 값은 언제나 유일해야 합니다.
<IterationSample.js>
const IterationSample = () => {
const names = ['눈사람','얼음','눈','바람'];
const nameList = names.map((name,index)=> <li key={index}>{name}</li>);
return <ul>{nameList}</ul>
}
export default IterationSample;
고유한 값이 없으면 index값을 key값으로 사용한다.
6.4 유동적인 데이터 렌더링
초기 상태 설정하기 => 데이터 추가 기능 구현하기 => 데이터 제거 기능 구현하기
6.4.1 초기 상태 설정하기
IterationSample 컴포넌트에서 useState를 사용하여 상태를 설정
세 가지 상태 사용 => 데이터 배열, 텍스트 입력 input, 데잍 배열에서 새로운 항목을 추사할 때 사용할 고유 id를 위한 상태
<IterationSample1.js>
import {useState} from 'react';
const IterationSample1 = () => {
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 (
<>
<input value={inputText} onChange={onChange}></input>
<button onClick={onClick}>추가</button>
<ul>{namesList}</ul>;
</>
)
}
export default IterationSample1;
key값을 index eotls name.id 값으로 지정했다.
6.4.2 데이터 추가 기능 구현하기
<IterationSample1.js>
import {useState} from 'react';
const IterationSample1 = () => {
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,
text : inputText
});
setNextId(nextId+1); // nexttId 값에 1을 더해 준다
setNames(nextNames); // names 값을 업데이트한다
setInputText(''); //inputText를 비운다
}
const namesList = names.map(name=> <li key={name.id}>{name.text}</li>);
return (
<>
<input value={inputText} onChange={onChange}></input>
<button onClick={onClick}>추가</button>
<ul>{namesList}</ul>;
</>
)
}
export default IterationSample1;
배열에 새 항목을 추가할 때 push함수 대신 concat을 사용
push 함수 => 기존 배열 자체를 변경
concat 함수 => 새로운 배열을 만듬
onClick에서는 새로운 항목을 추가할 때마다 객체의 id값은 nextId를 사용하도록 하고, 클릭할 때마다 1이 올라가도록 구현했다
6.4.3 데이터 제거 기능 구현
각 항목을 더블클릭했을 때 해당 항목이 화면에서 사라지는 기능을 구현
'불변성'을 유지하며 업데이트 해야 한다.
불변성을 유지하면서 배열의 특정 항목을 지울 때는 배열의 내장 함수 filter를 사용
<IterationSample2.js>
//데이터 제거 기능
import {useState} from 'react';
const IterationSample2 = () => {
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,
text : inputText
});
setNextId(nextId+1); // nexttId 값에 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}></input>
<button onClick={onClick}>추가</button>
<ul>{namesList}</ul>;
</>
)
}
export default IterationSample2;
6.5 정리
반복되는 데이터를 렌더링하는 방법을 배우고 이를 응용하여 유동적인 배열을 다뤘다.
컴포넌트 배열을 렌더링할 때는 key값 설정에 항상 주의해야합니다/
key값은 유일해야하고 key값이 중복된다면 렌더링 과정에서 오류가 발생
상태 안에서 배열을 변형할 때는 배열에 접근하여 수정하는 것이 아니라 concat, filter등의 내장함수를 사용