본문 바로가기

FrontEnd

[3분 리액트] React18의 useInsertionEffect 훅에 대해 알아보자

반응형

원문 : https://blog.saeloun.com/2022/06/02/react-18-useinsertioneffect

 

Know about the useInsertionEffect hook in React 18

Ruby on Rails and ReactJS consulting company. We also build mobile applications using React Native

blog.saeloun.com

TLDR :

useInsertionEffect는 useLayoutEffect가 동작하기 전에 스타일을 먼저 조작하게 해주는 훅이다.

css 라이브러리를 개발하는 케이스거나 특이 케이스가 아니면 볼일 없으실듯...


React 18은 동시 렌더링을 위한 기반을 제공합니다.
사용자가 React의 동시 렌더링 기능을 최대한 활용할 수 있도록 몇 가지 새로운 API가 도입되었습니다.
새로운 useInsertionEffect 후크를 다룰 것입니다.

CSS-in-JS의 문제점

CSS 라이브러리는 즉시 새 규칙을 생성하고 <style> 태그와 함께 문서에 삽입합니다.
이러한 라이브러리의 경우 성능에 영향을 줄 수 있으므로 <style> 태그를 삽입할 시기를 알아야 합니다.
  • CSS 규칙을 추가하거나 제거할 때 브라우저는 모든 규칙을 거의 다시 계산해야 합니다.
  • 그런 다음 변경된 규칙뿐만 아니라 이미 존재하는 모든 규칙을 같이 다시 적용해야 합니다.

즉, React가 렌더링되는 동안 모든 프레임의 모든 DOM 노드에 대해 모든 CSS 규칙을 다시 계산합니다.

이것은 매우 느립니다. 브라우저의 최적화는 이 문제를 방지하는 데 도움이 되지 않습니다.

 

이를 피하는 한 가지 방법은 DOM 업데이트 시기를 관리하는 것입니다.
DOM 변경과 동시에 CSS 규칙을 조작해야 합니다.
이는 React가 DOM을 변경할 때,
레이아웃에서 (스타일)정보를 읽기 전과 브라우저에서 콘텐츠를 보이기 전 시점일 수 있습니다.
이 동작은 useLayoutEffect 훅과 유사합니다. 하지만 해당 훅은 스타일을 삽입하는 데는 사용할 수 없습니다.

왜 useLayoutEffect는 안되나요?

useLayoutEffect 훅은 DOM에서 레이아웃을 읽고 동기적으로 다시 렌더링하는 데 사용됩니다.
스타일을 삽입하는 어떤 컴포넌트와 레이아웃을 읽는 어떤 컴포넌트가 있다고 가정합니다.
  • useLayoutEffect 훅을 사용하여 스타일을 삽입하면 레이아웃이 단일 렌더링 패스에서 여러 번 계산됩니다.
  • 또한 CSS가 삽입되기 전에 하나의 훅이 레이아웃을 읽으려고 하면 잘못된 레이아웃을 읽게 됩니다.

해당 문제를 해결하기 위해 useInsertionEffect라는 새로운 훅이 도입되었습니다.

The useInsertionEffect hook

useInsertionEffect(didUpdate);
useInsertionEffect의 시그니처는 useEffect와 동일합니다. 그러나 모든 DOM 조작 전에 동기적으로 실행됩니다.
useLayoutEffect에서 레이아웃을 읽기 전에 <style> 또는 SVG <defs>와 같은 전역 DOM 노드를 삽입하는 데 사용해야 합니다.
실제로 이러한 CSS 라이브러리 이외의 다른 용도로 사용되는 것은 아닙니다.
이 훅은는 스코프가 제한되어 있어 ref에 액세스할 수 없으며 업데이트를 예약할 수 없습니다. (useTransition)
//Source code - https://github.com/reactwg/react-18/discussions/110

function useCSS(rule) {
  useInsertionEffect(() => {
    if (!isInserted.has(rule)) {
      isInserted.add(rule);
      document.head.appendChild(getStyleForRule(rule));
    }
  });
  return rule;
}
function App() {
  let className = useCSS(rule);
  return <div className={className} />;
}

참고: useInsertionEffect 효과는 서버에서 발생하지 않습니다.
후크에 대해 더 알고 싶다면 여기에서 PR(the PR)과 더 많은 토론(more discussion here)을 확인하세요.

 

 

반응형