useEffect

  • useEffect: componentDidMount, componentDidUpdate 이후에 발생하는 코드를 넣음
  • 순수 함수는 참조 투명성을 가지는데 (부작용이 없음) useEffect는 이름에서 드러나듯 함수 컴포넌트가 부작용을 이용하는 도구다.
  • 계속 마운트되는 부분의 라이프사이클을 관리
  • 클래스 컴포넌트에서는 componentDidMount() 등의 함수를 썼었는데 넘 번거로워서 생김

직접 써보기

setInterval로 1초마다 초를 업데이트하는 함수가 있다.

function App() {
  const [second, setSecond] = useState(0);

  setInterval(() => {
    setSecond(second +1);
  },1000);

  return (
    <div>
      <p>{second}</p>
    </div>
  )
}

이 함수의 문제점은 1초마다 함수 전체가 새로 마운트 된다는 거다.
그러면 setInterval 함수를 또 시작한다.

console log

setInterval 안에서 console.log 함수를 찍으면 이렇게 이상한 결과가 나온다.
setInterval() 함수가 대략 1초마다 계속 실행되며 점점 쌓인다.
이런 경우에 useEffect()를 사용하면 된다!

function App() {
  const [second, setSecond] = useState(0);

  useEffect(()=> {
    let interval = setInterval(()=> {
      console.log(second);
      setSecond(second+1);
    }, 1000);

    return () => {
      clearInterval(interval);
    }
  }, [second]);

  return (
    <div className="App">
      <p>{second}</p>
    </div>
  )
}

이렇게 하면 마운트, 언마운트가 반복되며 second가 1초마다 1씩 늘어난다.

useEffect(() => {
  console.log("mount")
  return () => {
    console.log("unmount')       // 언마운트(cleanup) 안 하면 요청이 반복적으로 발생
  }
}, [second]);                   // mount에 의존적인 변수(dependencies) 삽입

추가로, useEffect 잘못 쓰고 계신겁니다.라는 글에 따르면 리액트18의 strict mode에서는 렌더링을 두번씩 하는데 그럴 경우 불필요한 상태 변경/리렌더링이 있을 수 있으니 useEffect에 클린업함수를 꼭 넣어줘라, 연산이 비싸면 useMemo 써라, react-query 등 캐시된 데이터를 써라고 한다.