Next.js
Hydration
Jotai 支持使用 useHydrateAtoms
进行 atoms 的 hydration。你可以在这里查看该 hook 的文档。
与路由同步
可以将 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 Roadmap 中有关于事件拦截和 hash 处理的计划。但是,目前还没有 ETA,也不清楚它会是什么样子。目前,当你尝试使用atomWithHash()
时,只有在页面重新加载或组件重新渲染时,你才能获取到带有数据的 atom,而不是通过路由导航。建议你将setHash
选项设置为replaceState
,因为 Next.js 似乎在后台使用 window.history,这将允许用户使用浏览器的后退按钮。
你不能在服务器端渲染中返回 promises
需要注意的是,你不能在 SSR 中返回 promises - 但是,你可以在 atom 定义中防止这种情况。
如果可能的话,使用 useHydrateAtoms
来从服务器 hydrate 值。
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" 模式。在 SSR 场景中,这成为一个问题,因为这个全局存储保持活跃,并在多个请求之间共享,这可能导致 bugs 和安全风险。
为了将存储的生命周期限制在一个请求的范围内,你需要在你的应用的根部(或者如果你只在应用的一部分使用 Jotai,那就是那部分的子树)使用 Provider。
import { Provider } from 'jotai'function App({ Component, pageProps }: AppProps) {return (<Provider><Component {...pageProps} /></Provider>)}
在这种情况下:
Provider
将持 有其子树中使用的 atoms 的状态,而不是全局存储。Provider
的生命周期将与应用本身相同,而由于应用在每个 SSR 请求上都会被重新创建,我们实际上将存储的生命周期限制在了一个请求内。
SWC 插件
Jotai 提供了 SWC 插件,以便在使用 Next.js 开发时获得更好的 DX。在 SWC 部分找到更多信息。
示例
时钟
HN 文章
Next.js 仓库
npx create-next-app --example with-jotai with-jotai-app
这是一个链接。