React 18 - useSyncExternalStore

Min Su Kwon·2024년 2월 13일

React

목록 보기
2/4
post-thumbnail

개요

useSyncExternalStore 훅은 React 18에서 등장한 신규 훅으로, 리액트가 외부 저장소의 변경사항을 "구독"할 수 있도록 도와주는 훅이다.

18버전에 들어오면서 리액트는 useTransition, useDeferredValue와 같이 렌더링을 일시중지하거나, 뒤로 미루는 등의 동시성 최적화를 도와줄 수 있는 훅들이 사용가능해졌다.

하지만 리액트에서 이렇게 동시성 렌더링이 가능해지면서, 외부 저장소의 데이터를 참조하는 컴포넌트를 렌더링할때 같은 시기에 렌더링을 했지만, 서로 다른 시점의 데이터를 참조할 수도 있는 Data Tearing 문제가 발생할 수 있게됐다.

이 문제를 해결해주는 훅이 바로 useSyncExternalStore 훅이다.

훅 시그니쳐

useSyncExternalStore(
  subscribe: (callback) => Unsubscribe,
  getSnapshot: () => State,
  getServerSnapshot?: () => State
)
  • subscribe
    • 콜백함수를 받아 스토어에 등록하는 용도로 사용된다. 스토어에 있는 값이 변경되면 콜백함수가 호출되어야 하며, 콜백이 호출되면useSyncExternalStore가 이 훅을 사용하는 컴포넌트를 리렌더링한다.
  • getSnapshot
    • 컴포넌트에 필요한 현재 스토어의 데이터를 반환하는 함수로, 스토어가 변경되지 않았다면 매번 함수를 호출할 때마다 동일한 값을 반환해야한다. 스토어에서 값이 변경됐다면, 이 값을 이전 값과 Object.is로 비교해 정말로 값이 변경됐다면 컴포넌트를 리렌더링한다.
  • getServerSnapshot
    • 옵셔널 값으로, 서버 사이드 렌더링 하이드레이션하는 도중에만 사용된다. 서버사이드에서도 사용되는 훅이라면 반드시 이 값을 넘겨줘야하며, 클라이언트의 값과 불일치가 발생할 경우 오류가 발생한다.

사용예시

일반적인 애플리케이션을 작성하는 상황에서는 크게 쓸 일이 많지만, 상태관리 라이브러리를 작성하거나, 리액트 외부의 무언가에 대한 값이 필요하고, 값이 변경될때마다 리렌더링이 수행되어야하는 케이스에 사용하면 적절하다.

DOM, 글로벌 변수, 외부 상태관리 라이브러리 등을 사용할 때 사용할 수 있으며, 아래는 예시로 작성해본 window.innerHeight 값에 대한 useInnerHeight 훅이다.

import { useSyncExternalStore } from "react";

function subscribe(callback) {
  window.addEventListener("resize", callback);
  return () => {
    window.removeEventListener("resize", callback);
  };
}

const useInnerHeight = () => {
  const innerHeight = useSyncExternalStore(
    subscribe,
    () => window.innerHeight
  );

  return innerHeight;
};

export default useInnerHeight;

첫번째 인수인 subscribe에는 resize 이벤트를 활용해서 innerHeight 값이 변경되는 상황에서 리렌더링이 발생할 수 있도록 해주고, 두번째 인수인 getSnapshot으로 window.innerHeight 값 반환을 통해 최신값을 받아올 수 있도록 커스텀 훅을 작성했다.

Reference

profile
이제 막 커리어를 시작한 소프트웨어 엔지니어입니다. 배운 것을 정리하면서 조금 더 깊이 이해하려는 습관을 들이려고 합니다. 피드백은 언제나 환영입니다.

0개의 댓글