벨로퍼트 모던 리액트 내용을 일부 정리했습니다. (아래는 생략된 코드가 많으니 자세한 것은 원문 링크를 참고하세요)
리액트에서 배열을 컴포넌트의 상태로서 관리할 수 있습니다. 초기 세팅은 아래처럼 useState 로 선언을 하고 초기값에 배열을 담아 둡니다.
const [users, setUsers] = useState([
{
id: 1,
username: 'velopert',
email: 'public.velopert@gmail.com',
active: true,
},
{
id: 2,
username: 'tester',
email: 'tester@example.com',
active: false,
},
{
id: 3,
username: 'liz',
email: 'liz@example.com',
active: false,
},
]);
위 배열에 변화를 줄 때는 객체와 마찬가지로 불변성을 지켜주어야 합니다. 배열의 push, splice, sort 등을 사용하면 안되고, 사용하더라도 기존의 배열을 복사한 후 써야 합니다. 불변성을 지키며 배열에 새 항목을 추가하는 방법은 spread 연산자를 쓰거나 concat 함수를 사용하는 방법 두가지 입니다. (concat 함수는 기존 배열 수정하지 않고, 새로운 원소 추가한 새 배열 만듬)
// spread 연산자
const onCreate = () => {
const user = { // 사용자가 새로 입력한 값 담고
id: nextId.current,
username,
email,
};
setUsers([...users, user]); // 여기서 기존 배열에 넣기
};
// concat 함수
const onCreate = () => {
const user = {
id: nextId.current,
username,
email,
};
setUsers(users.concat(user)); // 여기서 사용
};
배열의 특정 항목을 지우고 싶다면, 삭제 버튼에 콜백 함수로(삭제 함수를 프롭스로 전달 받는다면) 해당 값의 id 값을 파라미터로 담아 전달해야 합니다.
<button onClick={() => onRemove(user.id)}>삭제</button>
이렇게 전달한 값을 불변성을 지키며 업데이트하려면 filter 함수를 사용해야 합니다. (배열에서 특정 조건을 만족하는 원소들만 추출해 새로운 배열 생성)
const onRemove = id => {
setUsers(users.filter(user => user.id !== id));
};
// setUsers 로 배열을 바꾸어 주는데 선택한 것의 user.id 가 기조 id 와 다른 것들만 답는다. 같은 것, 선택한 것은 제외하고 담는다.
이제 배열 항목을 수정해보겠습니다. 배열안에 active 값에 따라 폰트 색상이 바뀌도록 아래 처럼 세팅하고,
<b
style={{
cursor: 'pointer',
color: user.active ? 'green' : 'black',
}}
>
{user.username}
</b>
onToggle 함수를 만들어서 수정합니다. 이때도 배열의 불변성을 고려해 map 함수를 사용할 수 있는데, id 값을 비교해서 id 가 다르면 그대로 두고, 같다면 active 값을 반전시키도록 합니다. 선택한 요소의 id 값을 콜백함수의 파라미터로 전달하는 방식은 위 제거하기와 유사합니다. onToggle 함수를 아래와 같이 작성하고,
const onToggle = id => {
setUsers(
users.map(user =>
user.id === id ? { ...user, active: !user.active } : user
)
);
};
onClick 이벤트에 onToggle 함수를 넣어줍니다.
<b
style={{
cursor: 'pointer',
color: user.active ? 'green' : 'black',
}}
onClick={() => onToggle(user.id)}
>
{user.username}
</b>