JotaiJotai

Jotai
React 原始而灵活的状态管理

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>
)
}

在这种情况下:

  1. Provider 将持有其子树中使用的 atoms 的状态,而不是全局存储。
  2. Provider 的生命周期将与应用本身相同,而由于应用在每个 SSR 请求上都会被重新创建,我们实际上将存储的生命周期限制在了一个请求内。

SWC 插件

Jotai 提供了 SWC 插件,以便在使用 Next.js 开发时获得更好的 DX。在 SWC 部分找到更多信息。

示例

时钟

HN 文章

Next.js 仓库

npx create-next-app --example with-jotai with-jotai-app

这是一个链接