使用 Zustand 插件追踪状态变化
Zustand 是一个非常快速且极简的状态管理解决方案,可以替代 Redux 等方案。借助我们的 Zustand 插件,你可以在应用程序的整个生命周期中追踪状态的变化。
可以使用以下命令轻松安装该插件:
npm i @openreplay/tracker-zustand
在 Next.js 应用中使用该插件
Section titled 在 Next.js 应用中使用该插件注意:本示例的完整源代码位于此 Github 仓库 中,如果你需要更多细节,请查看它。
我使用的 Context provider 允许配置 Tracker Plugins,因此在安装插件之后,我们将修改 _app.tsx 文件,添加下面的 import 语句:
import trackerZustand from '@openreplay/tracker-zustand'
然后,主 App 函数应该看起来像这样:
export default function MyApp({ Component, pageProps }: AppProps) {
const Layout = (Component as any).Layout || Noop
useEffect(() => {
document.body.classList?.remove('loading')
}, [])
let plugins = [
{
fn: trackerZustand,
name: 'zustand',
},
]
return (
<TrackerProvider
config={{
plugins
}}
>
<Head />
<ManagedUIContext>
<Layout pageProps={pageProps}>
<Component {...pageProps} />
</Layout>
</ManagedUIContext>
</TrackerProvider>
)
}
这将自动随 tracker 一起初始化该插件,并且还会提供执行插件主函数所返回的数据。
接下来要做的是创建一个 store,稍后我们会将电商网站中的商品添加到这个 store 中。
使用 Zustand 插件创建 store
Section titled 使用 Zustand 插件创建 store使用该插件需要你改变通常实例化 Zustand store 的方式,因此你可以放心地复制粘贴以下代码作为模板:
import create from 'zustand'
const productStore = null
export const useProductsStore = (logger) => {
if (!productStore) {
//use a singleton pattern to make sure we only create the store the first time around
productStore = createProductStore(logger)
}
return productStore
}
function createProductStore(logger) {
return create(
logger((set) => ({
products: [],
addProduct: (p) =>
set((state) => {
const prodFound = state.products.find((prod) => {
return p.id == prod.id
})
if (prodFound) {
p.amount = prodFound.amount + 1
} else {
p.amount = 1
}
return {
products: [...state.products.filter((prod) => p.id != prod.id), p],
}
}),
}))
)
}
导出的函数会在第一次使用时创建 store,但之后只会简单地返回已存在的 store。
另一方面,createProductStore 函数会创建 store,为 addProduct 方法设置逻辑,并使用我们提供给它的 logger 函数。你可能已经猜到了,这个 logger 正是我们使用 Zustand 插件时所获得的那个。
当 store 准备好之后,我们就可以开始向其中添加商品了。
向我们的 store 添加商品
Section titled 向我们的 store 添加商品store 导出了 addProduct 方法,它负责追踪我们购物车中的商品。
要将该函数导入到你的代码中,你需要:
- 导入并使用 Tracker 的 context provider。
- 从 context 中获取 pluginsReturnedValue 属性。
- 使用它来调用 zustand 方法(请注意,该方法是以我们在上面配置插件时所用的 name 属性来命名的),并传入一个字符串属性来为 store 命名(这个名称会在回放期间使用)。
- zustand 方法会返回 logger,我们将在调用 zustand 的 useProductStore hook(即我们为 store 创建的那个)时使用它。
这一切看起来很繁琐,但本质上都可以归结为:
const { pluginsReturnedValues } = useContext(TrackerContext)
const useProductStoreTracked = useProductsStore(
pluginsReturnedValues.zustand('products_store')
)
const { addProduct } = useProductStoreTracked()
现在,你只需调用 addProduct 方法,它就会把购物车中的商品添加到 store 中。
从 store 中读取数据
Section titled 从 store 中读取数据正如你大概能猜到的,如果你想从 Zustand store 中读取数据,你需要执行同样的一组步骤。但我们不再取用 addProduct 方法,而是解构出 products 数组。
像这样:
const { pluginsReturnedValues } = useContext(TrackerContext)
const useProductStoreTracked = useProductsStore(
pluginsReturnedValues.zustand('products_store')
)
const { products } = useProductStoreTracked()
然后你就可以像往常一样遍历这些商品:
<div>
{products.map((p: Product, idx: Number) => {
return (
<div key={+idx}>
{p.name}({p.amount})
</div>
)
})}
</div>
上面的代码会遍历商品列表并将它们渲染到屏幕上。每当你向 store 添加另一个商品时,这里也会随之更新。
将状态与 session replay 同步
Section titled 将状态与 session replay 同步要在回放期间查看状态变化,只需点击右下角新出现的 Zustand 选项卡:

点击它后,你将看到 store 的内容,并能够了解它是如何变化的以及其中保存的数据:

请注意 store 的名称,它实际上就是我们第一次调用 zustand 方法时所使用的名称。
如果你使用的不是 Next.js 而是其他框架,使用方式应该类似,关键在于你创建 store 的方式。只要你能找到在创建 store 时使用 logger 函数的方法,你就能够在回放期间追踪状态。
你可以查看此仓库,获取一个使用 Zustand 插件的可运行 Next.js 应用的完整源代码。
如果你在项目中设置 Zustand 插件时遇到任何问题,请通过我们的 Slack 社区 联系我们,直接向我们的开发者提问!