React Hooks - useEffect

sanha_OvO·2021년 11월 25일
0

React

목록 보기
6/13

Side Effect

Side Effect : 부작용, 부수효과.
이름만 들어서는 약간 부정적인 의미를 가진 것 같기도 하다.

하지만 함수 컴포넌트에서 Side Effect는 단순히 함수 실행시 함수 외부의 상태를 변경하는 연산을 뜻하며,
렌더링외의 함수 외부 환경에 영향을 주는 어떠한 이벤트라고 할 수 있겠다.
_ex) API 호출, Data Fetching, 이벤트 처리함수 등록 및 해제_

함수 컴포넌트의 리턴값은 UI 요소이며, 상태값과 props의 변화가 있을 때 마다 함수가 실행된다.
즉, 컴포넌트가 렌더링될 때 마다 함수 body에 있는 로직이 실행되며, 이는 렌더링과 무관한 로직이 렌더링 과정마다 실행되므로 렌더링 자체의 성능에 영향을 악영향을 줄 수 있게된다.

useEffect는 렌더링과 무관한 Side Effect를 실행시킬 수 있게끔하는 리액트의 내장 훅이다.


Rendering Cycle과 useEffect

useEffect를 좀더 폭넓게 활용하려면 리액트 컴포넌트의 Rendering Cycle에 대한 이해가 필요하다.

리액트 컴포넌트의 렌더링 사이클에 따른 useEffect의 생명주기는 아래 그림과 같다.

  1. 컴포넌트가 렌더링된다. 최초로 진행되는 렌더링은 브라우저에 처음으로 그려진다(mount).
  2. useEffect 첫 번째 인자로 넘겨준 부수 효과 함수가 실행된다.
  3. 리렌더링(re-render)이 일어나게되는 경우(stateprops가 변경된 경우), useEffect는 두 번째 인자에 들어있는 의존성 배열을 체크한다. 위에서 언급한 것처럼 useEffect에 인자로 넘긴 배열에 따라 부수 효과 함수를 실행하거나 혹은 실행하지 않는다.
  4. 만약 앞에서 일으킨 Effect에서 state나 props를 변경시켰다면 다시 한번 리렌더링이 된다.
  5. 이 후 컴포넌트가 필요 없어지면 화면에서 사라지게 된다(unmount).

useEffect의 사용

useEffect 훅 내의 함수는 부수 효과 함수라고 한다.
부수효과 함수는 렌더링 이후 호출되어 실행되어지고, 컴포넌트가 사라지기 직전에 마지막으로 호출이된다.

const Example = () => {
  const [count, setCount] = useState(0);
  
  useEffect(() => {
  	document.title = `update count : ${count}`;
  });
  
  return (
  	<div>
      <button onClick={() => setCount(prev => prev+1)}>push</button>
    </div>
  );
}

위 예제를 예로 들면 버튼을 클릭할 때마다 리렌더링이 일어나고 렌더링 이후 useEffect가 실행된다.

하지만 이런식으로 상태값 하나 바뀌었다고 매 렌더링마다 useEffect를 호출하는 것은 성능 저하를 유발한다.

const Example = () => {
  const [count1, setCount1] = useState(0);
  const [count2, setCount2] = useState(0);
  
  useEffect(() => {
  	document.title = `update count : ${count1}`;	
  }, [count1]); // count1의 값이 변경되었을 때만 useEffect가 실행된다.
  
  return (
  	<div>
      <button onClick={() => setCount1(prev => prev+1)}>count1 push</button>
      <button onClick={() => setCount2(prev => prev+1)}>count2 push</button>
    </div>
  );
}

useEffect는 부수효과 함수 외에도 의존성 배열(dependancy array)을 인자로 받을 수 있는데 이 경우 배열 내의 값이 바뀌는 경우만 useEffect를 실행하게 할 수 있다.

또 useEffect에 두번째 인자로 빈 배열[]을 넣으면 컴포넌트의 첫 렌더링 이후 한번 실행되고, 다른 값의 변경이 일어나는 경우에도 실행되지 않게 할 수 있다.

useEffect는 unmount될 때 (이전 클래스형 컴포넌트의 componentWillUnmount와 같은) 클린 업 함수를 실행시킬 수 있도록 만들어 졌다.

const Example = () => {
  const [scrollCount, setScrollCount] = useState(0)
  const onScroll = () => {
    setScrollCount(prev => prev + 1)
  }
  
  useEffect(() => {
  	document.addEventListener("scroll", onScroll)	
    
    return () => window.removeEventListener("scroll", onScroll)
  }, []); // 컴포넌트가 마운트될 때 onScroll을 이벤트리스너에 등록하고, 언마운트될 때 해제한다.
  
  return (
  	<div>
      <p>scroll! : {scrollCount}</p>
    </div>
  );
}

위 예제처럼 useEffect에 인자로 넣어준 부수 효과 함수에 클린 업 함수를 반환해주면 된다.
그러면 컴포넌트가 unmount될 때 useEffect는 반환된 클린 업함수를 실행하고 컴포넌트는 화면에서 사라지게 된다.

profile
Web Developer / Composer

0개의 댓글