최근 하고있는 프로젝트에서 토글 형태의 버튼을 만들 일이 있었다.
클릭하면 토글 하나만 색이 칠해지면 되는, 그런 간단한(?) 버튼인데 하다가 자꾸 막혀서, 왜 내 방법이 안되지? 하며 고민했다.
id값을 value로 하는 조금 얼척없는 실수에 시간을 많이 소비했지만, 이 문제를 푸는 데 있어 공식 홈페이지의 리액트 배열 state 업데이트 부분을 공부 했던 게 아주 매우 엄청 큰 도움이 됐다.
이 스터디를 한 걸 얼마나 잘 했는지 ..!
JavaScript에서 배열은 변경 가능하지만 state에 저장할 때는 변경이 불가능한 것으로 취급해야합니다. 객체와 마찬가지로, state에 저장된 배열을 업데이트하려면, 새로운 배열을 만들고(또는 기존 배열을 복사본을 만듦) 새 배열을 사용하도록 state를 설정해야합니다.
const lectureStatus = [
{ id: 1, statusName: "전체 목록", isActive: true },
{ id: 2, statusName: "수강 예정", isActive: false },
{ id: 3, statusName: "수강중", isActive: false },
{ id: 4, statusName: "수강 완료", isActive: false },
];
const [lecturesButton, setLectureButtons] = useState(lectureStatus);
const onClickActiveHandler = (e: React.MouseEvent<HTMLElement>) => {
const checkActiveLecture = [...lecturesButton];
const findActiveLecture = checkActiveLecture.find(
(a) => a.id === Number(e.currentTarget.id)
);
const changeActiveLecture = lecturesButton.map((lecture) => {
return lecture.id === findActiveLecture?.id
? { ...lecture, isActive: true }
: { ...lecture, isActive: false };
});
setLectureButtons(changeActiveLecture);
};
{lecturesButton.map((lecture) => {
const { id, statusName, isActive } = lecture;
return (
<div key={id}>
{isActive ? (
<Button
shape="round"
type="primary"
danger
onClick={onClickActiveHandler}
id={String(id)}
>
{statusName}
</Button>
) : (
<Button
shape="round"
onClick={onClickActiveHandler}
id={String(id)}
>
{statusName}
</Button>
)}
</div>
);
})}
조금 어렵고(?) 복잡하게 보이는 코드지만, 차근차근보면 금방 알 수 있다.
const [lecturesButton, setLectureButtons] = useState(lectureStatus);
여기 lecturesButton useState에는 initialState값인 lectureStatus가 들어있고, 아래에는 그 버튼을 그려준다.
type="primary" danger
상중요한부분은 onClick 됐을 때 어떻게 active한 버튼의 색이 바뀌는것이냐인데,
const onClickActiveHandler = (e: React.MouseEvent<HTMLElement>) => {
const checkActiveLecture = [...lecturesButton];
const findActiveLecture = checkActiveLecture.find(
(a) => a.id === Number(e.currentTarget.id)
);
const changeActiveLecture = lecturesButton.map((lecture) => {
return lecture.id === findActiveLecture?.id
? { ...lecture, isActive: true }
: { ...lecture, isActive: false };
});
setLectureButtons(changeActiveLecture);
};
const checkActiveLecture = [...lecturesButton]
const findActiveLecture = checkActiveLecture.find(
(a) => a.id === Number(e.currentTarget.id)
);
는 클릭한 값의 번호를 갖게된다.
const changeActiveLecture = lecturesButton.map((lecture) => {
return lecture.id === findActiveLecture?.id
? { ...lecture, isActive: true }
: { ...lecture, isActive: false };
});
setLectureButtons(changeActiveLecture);
와! 별 거 아니지만(나한테는 별거였음) 혼자 해결한 나 자신에게 박수 👏