리액트 배열 state 업데이트 (feat. 버튼 토글)

드엔트론프·2023년 4월 23일
0

react-study

목록 보기
4/4
post-thumbnail

들어가며

최근 하고있는 프로젝트에서 토글 형태의 버튼을 만들 일이 있었다.

클릭하면 토글 하나만 색이 칠해지면 되는, 그런 간단한(?) 버튼인데 하다가 자꾸 막혀서, 왜 내 방법이 안되지? 하며 고민했다.
id값을 value로 하는 조금 얼척없는 실수에 시간을 많이 소비했지만, 이 문제를 푸는 데 있어 공식 홈페이지의 리액트 배열 state 업데이트 부분을 공부 했던 게 아주 매우 엄청 큰 도움이 됐다.

리액트 비공식 번역 홈페이지

배열 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가 들어있고, 아래에는 그 버튼을 그려준다.

  • isActive의 상태에 따라 버튼은 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);
  };

1.

  • const checkActiveLecture = [...lecturesButton]
    로 기존 값을 복사해주고,

2.

const findActiveLecture = checkActiveLecture.find(
      (a) => a.id === Number(e.currentTarget.id)
    );

는 클릭한 값의 번호를 갖게된다.

3.

const changeActiveLecture = lecturesButton.map((lecture) => {
      return lecture.id === findActiveLecture?.id
        ? { ...lecture, isActive: true }
        : { ...lecture, isActive: false };
    });
  • findActiveLecture가 가진 id와 같은 id를 가진 친구는 isActive의 값을 true로, 나머지는 false로 바꿔준다.

4.

setLectureButtons(changeActiveLecture);

  • 바뀐 값을 setLectureButtons에 넣어주면 끝!

와! 별 거 아니지만(나한테는 별거였음) 혼자 해결한 나 자신에게 박수 👏

profile
왜? 를 깊게 고민하고 해결하는 사람이 되고 싶은 개발자

0개의 댓글