문제 상황
// 임계 시간을 초과했다면 슬립모드로 전환 useEffect(() => { const A = 3; const B = 5; const interval = setInterval(()=> setAliveState((previousState) => ({ ...previousState, isOnSleepMode: A < B, })),1000); return (): void => { clearInterval(interval); }; }, [aliveCount]);
상태를 설정하는 setAliveState의 호출은 setInterval로 인해 1초마다 매번 호출되고, 저장되는 상태값은 사실상 항상 똑같이 저장된다.
이렇게 되어있는 코드가 있고, useGetAliveState()로 상태를 가져와서 쓰는 컴포넌트가 있다고 가정하자.
해당 컴포넌트는 리렌더링 될까 안될까?
정답은 “해당 컴포넌트는 1초마다 리렌더링 된다”이다.
오브젝트를 담는 상태이고, 오브젝트는 매번 새로운 reference가 반환되므로 내용물은 같더라도 얕은복사로 검사 시에는 매번 다른 상태값으로 바뀌는 것으로 인식하기 때문이다.
개선 방안
조건을 먼저 검사하고, 조건에 부합할 때만 setState 함수를 호출하도록 수정해주자
// 임계 시간을 초과했다면 슬립모드로 전환 useEffect(() => { const A = 3; const B = 5; // eslint-disable-next-line @typescript-eslint/no-shadow const isOnSleepMode = A < B; const interval = setInterval(() => { if (isOnSleepMode) { setAliveState((previousState) => ({ ...previousState, isOnSleepMode, })); } }, 1000); return (): void => { clearInterval(interval); }; }, [aliveCount]);