자식 component가 재랜더링이 안된다면..(불변성의 중요성)

이무헌·2022년 11월 22일
0

react

목록 보기
11/19
  // 학생의 사전평가 기록
  const [studentPreEvaluationData, setStudentPreEvaluationData] = useState<
  preTestResult[]| null  >(null);
  //학생의 사후평가 기록
  const [studentPostEvaluationData, setStudentPostEvaluationData] = useState<
    postTestResult[] | null
  >(null);

두개의 state가 있다. 나는 지금부터 이 state를 파라미터로 넘겨 sort를 이용해 정렬 할 것이다.

 const sortByRecentDate = useCallback(
    async (preResult: preTestResult[], postResult: preTestResult[]) => {
      return new Promise<any>((resolve) => {
        if (trigger === "사전평가") {
          tempArray = preResult.sort((a: preTestResult, b: preTestResult) => {
            return new Date(b.date).valueOf() - new Date(a.date).valueOf();
          });
          resolve(tempArray);
        }
      });
    },
    [trigger]
  );

동기적으로 진행하기 위해 promise로 진행하였다.
그 후 setSortedData 함수를 만들어 state를 바꾸자

const setSortedData = async () => {
    const newArray: preTestResult[] = await sortByRecentDate(
      studentPreEvaluationData as preTestResult[],
      studentPostEvaluationData as preTestResult[]
    );
    setStudentPreEvaluationData(newArray);
  };

파라미터도 잘 넘어갔고..이제 버튼을 클릭하여보자

 <Sort
onClick={() => {
setSortedData();
}}
                  />

??정렬이 되지 않는다... 시간순으로 정렬이 되어야 하는데 정렬이 되지 않는다...
디버그를 찍어본 결과 위 함수를 선언한 컴포넌트는 재랜더링이 진행이 되지만, 정작 state를 넘겨서 정보를 표시해야하는 자식 component는 재랜더링이 되지 않는다..!

//자식 컴포넌트
{!isLoading ? (
                <EccEvaluationTable
                  studentInfo={studentInfo}
                  studentPreEvaluationData={studentPreEvaluationData}
                  studentPostEvaluationData={studentPostEvaluationData}
                  trigger={trigger}
                  isLoading={isLoading}
                  setTrigger={setTrigger}
                >
                  <Link to="/preTest">
                    <PreEccEvaButton style={{ marginTop: 40 }}>
                      사전평가
                    </PreEccEvaButton>
                  </Link>
                  <Link to="/postTest">
                    <PostEccEvaButton>사후평가</PostEccEvaButton>
                  </Link>
                </EccEvaluationTable>
              ) : (
                <h2>데이터를 불러오고 있습니다..</h2>
              )}

studentPreEvaluationData={studentPreEvaluationData}
studentPostEvaluationData={studentPostEvaluationData}
이 둘을 props로 넘겼고 위와 같이 setStudentPreEvaluationData() 를 사용해 state도 변경해 주었다...

근데 어째서 자식 컴포넌트는 재랜더링이 안될까?
바로 불변성 때문이다... state를 sort를 한 후 바로 tempArray에 할당을 하였고, 이 둘은 같은 주소를 참조하여 깊은복사가 되어있는 상태이다.. 그 상태에서 setState를 사용했으니 재랜더링이 일어나지 않는것이다..

const setSortedData = async () => {
    const newArray: preTestResult[] = await sortByRecentDate(
      studentPreEvaluationData as preTestResult[],
      studentPostEvaluationData as preTestResult[]
    );
    setStudentPreEvaluationData(**[...newArray]**);
  };

수정한 후 돌려보니 정상적으로 재랜더링이 일어났다...

앞으로 모든 prototype함수는 새로운 배열을 return 하는지 확인하자.. 새 배열을 return하지 않는 다면 spread operation 같은 방법을 이용해 얕은복사를 하여 불변성을 지키자 재랜더링이 안된다면 무조건!!!!!!!참조값을 변경하지 않아서이다! 속는셈 치고 spread operation 사용해보자

끝!

profile
개발당시에 직면한 이슈를 정리하는 곳

0개의 댓글