Epic React - advanced apis

김동하·2025년 3월 21일
0

react

목록 보기
32/32

영원한 우리 형 kent c dodds의 epic-react에서 배운 거 정리

1. flushSync

flushSync는 React에 제공된 콜백 내부의 모든 업데이트를 동기적으로 처리하도록 강제합니다. DOM이 즉시 업데이트되는 것을 보장합니다.

React18 부터 Automatic batching 적용되면서 렌더링 비용을 감소하는 이점을 얻고 있다.

하지만, 상태 변화로 인해 DOM의 즉각적인 업데이트 후 추가 작업을 진행해야 하는 경우가 있다(ref...) 그럴 때 사용하는 flushSync 함수

가령 위와 같은 상황이 있다고 가정하자. isEdit 일 때는 input이고, onSubmit을 이후 isEditfalse가 되어 button 이 렌더링 된다.

input에 value를 작성하고 onSubmit을 실행한 후, button을 focus하고 싶다고 하자.

하지만 state가 즉각적으로 업데이트 되지 않기 때문에 아래 buttonRef는 여전히 null 이고 buttonRef.current.focus()는 작동하지 않는다.

코드는 대략 아래와 같다.

위와 같은 문제를 해결하기 위해서 requestAnimationFrame 혹은 setTimeout과 같은 인위적으로 DOM 렌더링 타이밍을 맞추는 방법도 있겠지만, 퍼포먼스 등 여러 문제가 있다.

그래서 사용하는 것이 flushSync

flushSync을 통해 즉각적으로 상태가 변경되어 업데이트 된 DOM에서 Ref로 접근하여 focus까지 이루어진다. 하지만 flushSync는 리액트의 배치 업데이트를 위반하기(?) 때문에 'DOM 렌더링 후 즉각 Ref 접근'의 경우에만 사용한다고 한다.

2. useSyncExternalStore

useSyncExternalStore는 외부 store를 구독할 수 있는 React Hook입니다. useSyncExternalStore API는 기존 비 React 코드와 통합해야 할 때 주로 유용합니다. 하지만 가능하면 내장된 React state를 useState 및 useReducer와 함께 사용하는 것이 좋습니다.

useSyncExternalStore은 리액트18부터 동시성이 추가되면서 Tearing 현상이 발생하게 되었는데, 이를 해결하기 위해 추가된 api다.

외부 저장소, 즉 리액트를 제외한 모든 서드파티 라이브러리, 브라우저 api 등과 동기화를 맞추는 역할을 한다.

가령, use-media-query을 작성한다고 했을 때

이런 식으로 useStateuseEffect을 사용하여 window 객체의 matchMedia 함수를 사용해야 한다.

하지만 useSyncExternalStore을 사용하면 좀 더 깔끔하게 작성할 수 있다.

먼저 subscribe 함수를 만든다.

subscribe 함수에선 이벤트를 등록/해제한다.

그리고 getSnapshot을 만든다.

getSnapshot이 반환한 값과 저장소에 저장된 값이 다르면 리액트는 리렌더링하게 된다.

위 두 함수를 useSyncExternalStore에 인자로 넘기면 끝이다.

further

getServerSnapshot이 초기 클라이언트 렌더링에서 서버에서 반환한 것과 동일한 정확한 데이터를 반환하는지 확인하세요. 예를 들어 getServerSnapshot이 서버에서 미리 채워진 store 콘텐츠를 반환한 경우 이 콘텐츠를 클라이언트로 전송해야 합니다. 이를 수행하는 일반적인 방법 중 하나는 서버 렌더링 중에 window.MY_STORE_DATA와 같은 글로벌을 설정하는

만약, SSR을 사용한다고 가정하자.

useSyncExternalStore의 3번째 인자로 getServerSnapshot 인자를 넘기지 않으면 아래와 같은 에러가 나온다.

하지만, matchMediauseSyncExternalStore의 이벤트로 등록하게 되면 클라이언트와 서버가 hydration 할 때의 matchMedia의 초기값을 알 수가 없기 때문에 getServerSnapshot을 사용할 수 없다.

그런 경우에 suspense를 사용하여 hydration가 끝날 때까지 기다리는 편이 낫다.

추가적으로 해당 에러가 신경쓰인다면 아래와 같이 onRecoverableError를 통해 에러메시지를 무시할 수도 있다.

참고: epic-react

profile
프론트엔드 개발

0개의 댓글

관련 채용 정보