[hook]useEffect 와 useLayoutEffect

아토시스·2022년 8월 10일
0

React

목록 보기
4/7

설명을 이해하기 전 필수 개념 2가지

  • Render: DOM Tree를 구성하기 위해 각 element의 스타일 속성을 계산하는 과정
  • Paint: 실제 스크린에 Layout을 표시하고 업데이트하는 과정

useEffect

useEffect는 컴포넌트들이 renderpaint 된 후 실행된다. 비동기적(asynchronous)으로 실행된다.
paint 된 후 실행되기 때문에, useEffect 내부에 DOM에 영향을 주는 코드가 있을 경우 사용자 입장에서는 화면의 깜빡임을 보게된다. 이렇게 되면 불편한 사용자 경험으로 이어질 수 있다.


import { useEffect, useState } from "react";

function App() {
  const [age, setAge] = useState(0);
  const [name, setName] = useState("");
  
  useEffect(() => {
    setAge(25);
    setName("찬민");
  }, []);
  
  return (
    <>
      <div className="App">{`그의 이름은 ${name} 이며, 나이는 ${age}살 입니다.`}</div>
    </>
  );
}

export default App;

useEffect를 사용한 위 코드는 다음 순서대로 동작한다.

  1. < div >그의 이름은 이며, 나이는 0살 입니다.< /div> 를 paint
  2. effect 내부의 setNumber, setName 호출
  3. 재렌더링 수행 - < div >그의 이름은 찬민이며, 나이는 25살 입니다.< /div>
 물론 이렇게 간단한 DOM 구조라면 금방 렌더링할 수 있겠지만, 화면이 복잡해지면 체감할 수 있을 정도로 렌더링 시간이 증가하게 된다. 
 

useLayoutEffect 훅은 바로 이런 문제를 해결하기 위해 등장한 훅이다


useLayoutEffect

useLayoutEffect 는 컴포넌트들이 render 된 후 실행되며, 그 이후에 paint 가 된다. 이 작업은 동기적(synchronous) 으로 실행된다. paint 가 되기전에 실행되기 때문에 DOM 을 조작하는 코드가 존재하더라도 사용자는 깜빡임을 경험하지 않는다.

                                  화면에 DOM을 그리기 전에 Effect를 수행
import { useLayoutEffect, useState } from "react";

function App() {
  const [age, setAge] = useState(0);
  const [name, setName] = useState("");

  useLayoutEffect(() => {
    setAge(25);
    setName("찬민");
  }, []);

  return (
    <>
      <div className="App">{`그의 이름은 ${name} 이며, 나이는 ${age}살 입니다.`}</div>
    </>
  );
}

export default App;

useLayoutEffect를 사용한 위 코드는 다음 순서대로 동작한다.

  1. useLayoutEffect 내부의 setNumber, setName 호출

  2. < div >그의 이름은 찬민이며, 나이는 25살 입니다.< /div> 를 paint


결론

useLayoutEffect 는 동기적으로 실행되고 내부의 코드가 모두 실행된 후 painting 작업을 거친다. 따라서 로직이 복잡할 경우 사용자가 레이아웃을 보는데까지 시간이 오래걸린다는 단점이 있어, 기본적으로는 항상 useEffect 만을 사용하는 것을 권장한다고 한다. 구체적인 예시로는

  • 데이터 fetch
  • event handler
  • state reset

등의 작업은 항상 useEffect 를 사용하되,

const Test = (): JSX.Element => {
  const [value, setValue] = useState(0);

  useLayoutEffect(() => {
    if (value === 0) {
      setValue(10 + Math.random() * 200);
    }
  }, [value]);

  console.log('render', value);

  return (
    <button onClick={() => setValue(0)}>
      value: {value}
    </button>
  );
};

화면이 깜빡거리는 상황일 때, 예를들어 위와같이 state 가 존재하며, 해당 state 이 조건에 따라 첫 painting 시 다르게 렌더링 되어야 할 때는 useEffect 사용 시 처음에 0이 보여지고 이후에 re-rendering 되며 화면이 깜빡거려지기 때문에 useLayoutEffect 를 사용하는 것이 바람직하다고 한다.

간단히

  • useEffect의 이펙트는 DOM이 화면에 그려진 이후에 호출된다.

  • useLayoutEffect의 이펙트는 DOM이 화면에 그려지기 전에 호출된다.

  • 따라서 렌더링할 상태가 이펙트 내에서 초기화되어야 할 경우, 사용자 경험을 위해 useLayoutEffect를 활용하자!


참고 사이트 1
참고 사이트 2

profile
오늘보다 더 나은 내일이 되길 바라며

0개의 댓글