이 글은 단순히 리액트 공식 문서를 읽고 베꼈을 뿐이다!! 학습 목적이라면 공식 문서를 보는 걸 추천한다.

공식 문서
https://react.dev/reference/react/useSyncExternalStore
useSyncExternalStore – React
The library for web and native user interfaces
react.dev
useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot?)
- 외부 저장소와의 동기화를 도와주는 리액트 훅
- 반환값: 저장소에 있는 데이터의 snapshot
subscribe
- 인자로 '구독자' 하나를 받는 콜백 함수
- 외부 저장소의 '구독자 목록'에 '구독자'를 추가하는 기능 필요
- 반환값: 해당 '구독자'를 '구독자 목록'에서 제거하는 인자 없는 콜백 함수
- 이 '구독자'는 일종의 함수: 외부 저장소의 값을 변경한 후 외부 저장소에서는 이 구독자를 호출하여 snapshot을 다시 받아가야 한다는 것을 알려줘야 함
getSnapshot
- 외부 저장소에 저장된 값의 snapshot을 반환하는 함수
- 외부 저장소가 바뀌지 않았다면 몇 번 불러도 같은 값을 반환해야 함
- 반환한 값이
Object.is
로 비교했을 때 변하면 리렌더링
getServerSnapshot
(optional)- 서버에서 컴포넌트를 렌더링할 경우에 사용
- 외부 저장소의 초기 스냅샷을 반환하는 함수
getSnapshot
의 반환값은 바꿀 수 없어야(immutable) 함. 만약 외부 저장소의 값이 변할 수 있(mutable)다면 값이 바뀌었을 때 새로운 immutable snapshot을 반환해야 함. 만약 바뀌지 않았으면 캐싱된 이전 snapshot을 반환해야 함.- 리렌더링 시 다른 구독 함수를 넘겨주면 다시 구독함. 이게 싫으면 구독 함수의 정의를 컴포넌트 밖에서 해야 함.
사용법
외부 저장소 구독하기
- 대부분의 컴포넌트는 props, state, context로부터 본인이 필요한 정보들을 받음
- 하지만 가끔씩 컴포넌트는 리액트 외부의 저장소에서 값을 읽어올 필요도 있음
- 리액트 외부의 제삼의 상태 관리 라이브러리
- 변하는 값에 접근할 수 있고 그 값의 변화를 구독할 수 있는 브라우저 API
- 가능하다면 리액트에 내장된
useState
나useReducer
를 사용하는 것을 추천함 useSyncExternalStore
는 이미 존재하는 리액트가 아닌 코드들과 연동하는 데 쓰기 좋음
브라우저 API 구독하기
- 브라우저의 어떤 변하는 값을 구독하고 싶을 때
navigator.onLine
을 구독해서 인터넷 연결 상태가 바뀌었을 때 컴포넌트를 리렌더링시킬 수 있음
로직을 커스텀 훅으로 분리하기
- 일반적으로 컴포넌트에서 직접
useSyncExternalStore
를 부르지 않음 - 대신 특정한 대상을 구독하여 snapshot을 반환받는 로직으로 이루어진 커스텀 훅을 만들고 그걸 쓰는 게 일반적
서버에서 컴포넌트를 렌더링할 경우
- 서버에서 컴포넌트를 렌더링하면 브라우저 외부 환경에서 초기 HTML을 만든다는 뜻
- 브라우저에서만 사용할 수 있는 API를 쓴다면 작동하지 않음
- 제삼의 저장소를 사용한다면 이 저장소의 값이 서버와 클라이언트 두 곳에서 모두 동일하게 만들어야 함
getServerSnapshot
을 이용해서 서버 렌더링에서 사용할 초기값 지정 가능
문제 해결하기
The result of getSnapshot should be cached 오류가 떠요
getSnapshot
이 매 호출마다 새로운 객체를 반환한다는 뜻(메모리 주소가 다르다는 뜻)- 리액트는 이 함수를 쓴 후 이전의 값과
Object.is
로 비교해서 다르면 리렌더링함 - 우리가 기존에
useState
에서 상태를 바꿀 때 객체를 교체(replace)해서 리렌더링 시켰는데 근본적으로 같은 이유임 - 외부 저장소는 이전 snapshot을 그대로 기억했다가 만약 저장소가 바뀌지 않았으면 완전 똑같은 snapshot을 돌려줘야 함
제 구독 함수가 리렌더링될 때마다 호출돼요
- 컴포넌트의 렌더링 과정 내에 구독 함수를 정의하는 경우임
- 렌더링할 때마다 새로운 주소를 가진 구독 함수가 만들어지므로 계속 구독하는 셈
- 정 컴포넌트 안에서 정의해야겠으면
useCallback
쓰기
'리액트 공식 문서 읽기' 카테고리의 다른 글
33화: Built-in React Hooks (0) | 2024.02.17 |
---|---|
31화: useState (0) | 2023.07.16 |
30화: Reusing Logic with Custom Hooks (2) | 2023.06.22 |
29화: Removing Effect Dependencies (0) | 2023.06.22 |
28화: Separating Events from Effects (0) | 2023.06.22 |