useEffect와 useState의 무한루프 (feat. Derived State )

­김찬호·2021년 10월 20일
0

토이프로젝트를 진행하면서 useEffect 내부에서 setState를 호출하게끔 개발을 하였다.
내가 목표한 바는 아래와 같다.

  1. props를 state로 관리하자. (props 데이터를 한 번 더 가공해야 하기 때문)

  2. props가 갱신될 때 마다 state를 바꾸자. (props를 state로 관리해서)

const [tmp, setTmp] = useState(props.tmp);

//tmp = {first:"1", second:"2"}

useEffect(setTmp({...tmp, first:"3"}),[tmp])
    

이렇게 코드를 구현하면

1. useEffect가 호출됨
2. tmp가 갱신됨
3. useEffect가 호출됨
4. tmp가 갱신됨
....반복

이런 순서로 무한루프가 생겨버린다. 해결 방법은 props를 state로 관리하지 않는 것이었다.

https://reactiver.dev/review-react-derived-state 블로그를 참고 하였습니다.

props를 state로 관리하는 것을 Derived State 디자인 라고 부른다.
Derived State 상태로 컴포넌트를 작성하면 state로 관리하는 변수는 처음 마운트될 때 한 번만 할당되기 때문에 props가 변경된다고 해서 re-rendering이 되지 않는다.

때문에 props를 state로 관리하는 것을 피해야 한다.

solution

code 1

...
// props = {controlledValue:1}
const [state, setState] = useState(props)
return (
    <div>
      <span>{state.controlledValue}</span>
    </div>
  );

code 2

...
return (
    <div>
      <span>{props.controlledValue}</span>
    </div>
  );

code 1과 code2는 다르지 않다. 하지만 code 1처럼 props를 state로 관리하게 될 시

source of truth가 존재하지 않는다. 상위 컴포넌트에도 controlledValue가 존재하게 되고
하위 컴포넌트에도 controlledValue가 존재하게 되기 때문이다. 헷갈리기에 적합하다.
추가로 불필요한 코드도 생기며 state와 props는 react에서 다르게 관리하기 때문에 같은 cycle로 동작하지 않을 경우가 생길 수 있다.

느낀점

근본에 대해 깊이 공부할 필요가 있다고 느꼈다.

profile
주니어 개발자가 되고싶은 학부생

0개의 댓글