React - useEffect의 의존성에 관하여

BigbrotherShin·2020년 3월 16일
0

Frontend

목록 보기
9/31
post-thumbnail

함수(fn) 내부에서 쓰는 state를 배열로 넣는다.

useEffect(
  () => {
    doSomething(a, b);
  },
  [a, b], // deps array
);

배열 내에 여러 개의 값이 있다면 그중의 단 하나만 다를지라도 리액트는 effect를 재실행합니다.

이것이 의미하는 바는 다음과 같습니다. [count]를 useEffect의 두 번째 인수로 넣었다고 가정해 봅시다.

만약 count가 5이고 컴포넌트가 리렌더링된 이후에도 여전히 count는 변함없이 5라면 리액트는 이전 렌더링 시의 값 [5]를 그다음 렌더링 때의 [5]와 비교합니다. 배열 내의 모든 값이 같기 때문에(5 === 5) 리액트는 effect를 건너뛰게 됩니다.

count가 6으로 업데이트된 뒤에 렌더링하면 리액트는 이전에 렌더링된 값 [5]를 그다음 렌더링 시의 [6]와 비교합니다. 이때 5 !== 6 이기 때문에 리액트는 effect를 재실행합니다. 이를 활용하면 최적화가 가능합니다.

deps 배열의 state에 조건 사용하기

또한 특정 state가 특정한 condition 일 때만 effect를 재실행하고 싶다면 deps 배열의 state에 특정 조건을 넣는 것도 가능합니다.

그 이유는 리액트는 배열 내부의 값들이 이전 값과 비교하여 달라졌는지만 검사하기 때문입니다. [state === 5] 와 같이 특정 조건을 배열에 넣는다면, state === 5 자체가 하나의 boolean 값으로 인식됩니다. 따라서 state가 1, 2, 3 등일 때는 false 값을 가지고 있다가 state가 5가 된 후 렌더링 된 값은 true가 되어 false !== true 이기 때문에 리액트는 effect를 재실행하는 것입니다.

useEffect(() => {
  document.title = `You clicked ${count} times`;
}, [count === 5]); // count가 5일 때만 effect를 재실행합니다.

유의점

deps 배열에 객체를 넣는 건 추천되지 않습니다. 이전 렌더링과 현재 렌더링에서의 객체 값을 비교하기 어렵기 때문입니다. 객체를 넣기 위해서는 다음 예제와 같이 Obj && Obj[attr]를 deps 배열에 넣어주는 것이 좋습니다.

다음 예제에서 me는 초깃값이 null인 상태이며, 자료형은 객체입니다.

import React, { useEffect } from 'react';
import Router from 'next/router';

  useEffect(() => {
    if (me) {
     alert('로그인이 되어 메인 페이지로 이동합니다.');
     Router.push('/'); // id가 생기면 signup 페이지에서 메인 페이지로 이동
    }
  }, [me && me.id]); // JavaScript에서 객체는 undefined일 수 있으니,
// `me` 값이 확실히 존재하는 지 판단하기 위해 `&& me.id`를 붙여 guard를 해주어야 합니다.
profile
JavaScript, Node.js 그리고 React를 배우는

0개의 댓글