Next.js
Hydration
Jotai는 useHydrateAtoms
를 통해 아톰의 hydration을 지원합니다. 이 훅에 대한 문서는 여기에서 확인할 수 있습니다.
라우터와 동기화하기
Jotai를 라우터와 동기화할 수 있습니다. atomWithHash
를 사용하면 이를 구현할 수 있습니다:
const pageAtom = atomWithHash('page', 1, {replaceState: true,subscribe: (callback) => {Router.events.on('routeChangeComplete', callback)window.addEventListener('hashchange', callback)return () => {Router.events.off('routeChangeComplete', callback)window.removeEventListener('hashchange', callback)}},})
이렇게 하면 구독하려는 라우터 이벤트를 완전히 제어할 수 있습니다.
Next.js 13에서
Next.js 13부터는
Router.events.on()
에 몇 가지 변경 사항이 있어 더 이상 이벤트를 노출하지 않습니다. App Router 로드맵에 이벤트 가로채기 및 해시 처리에 대한 계획이 있지만, 이 기능이 언제 제공될지 또는 어떤 형태로 제공될지는 아직 알려지지 않았습니다. 현재atomWithHash()
를 사용하려고 할 때 라우터를 사용하여 네비게이션을 할 때는 아톰이 데이터와 함께 로드되지 않고, 페이지를 새로 고치거나 컴포넌트가 리렌더링될 때만 로드됩니다. 또한 Next.js가 백그라운드에서 window.history를 사용하는 것처럼 보이므로setHash
옵션을replaceState
로 설정하는 것이 좋습니다. 이렇게 하면 사용자가 브라우저의 뒤로 가기 버튼을 사용할 수 있습니다.
서버 사이드 렌더링에서는 Promise를 반환할 수 없음
서버 사이드 렌더링(SSR)에서는 Promise를 반환할 수 없다는 점을 주의해야 합니다. 하지만 atom 정의 내부에서 이를 방지할 수 있습니다.
가능하다면 useHydrateAtoms
를 사용하여 서버에서 값을 미리 채워넣는 것이 좋습니다.
const postData = atom((get) => {const id = get(postId)if (isSSR || prefetchedPostData[id]) {return prefetchedPostData[id] || EMPTY_POST_DATA}return fetchData(id) // Promise를 반환})
Provider
기본적으로 Jotai는 atom 값을 추적하기 위해 암시적 전역 스토어를 사용합니다. 이를 "provider-less" 모드라고 부릅니다. 하지만 SSR(서버 사이드 렌더링) 시나리오에서는 이 전역 스토어가 여러 요청 간에 공유되며 유지되기 때문에 버그와 보안 위험이 발생할 수 있습니다.
스토어의 수명을 단일 요청 범위로 제한하려면 앱의 루트(또는 앱의 일부에서만 Jotai를 사용하는 경우 하위 트리)에 Provider를 사용해야 합니다.
import { Provider } from 'jotai'function App({ Component, pageProps }: AppProps) {return (<Provider><Component {...pageProps} /></Provider>)}
이 경우:
Provider
는 전역 스토어 대신 하위 트리에서 사용되는 atom의 상태를 보관합니다.Provider
의 수명은 앱 자체와 동일하며, 앱이 각 SSR 요청마다 재생성되기 때문에 스토어의 수명도 단일 요청으로 제한됩니다.
SWC 플러그인
Jotai는 Next.js와 함께 개발할 때 더 나은 개발자 경험(DX)을 제공하기 위해 SWC 플러그인을 제공합니다. SWC 섹션에서 더 많은 정보를 확인하세요.
Examples
Clock
HN 게시물
페이지 라우터 데모:
앱 라우터 Stackblitz 데모
Next.js 저장소
npx create-next-app --example with-jotai with-jotai-app
여기 링크를 참고하세요.