什么是 zustand?
zustand 是一个状态管理库,简单易用。
在使用 react-scan 的时候,我发现我在 A 组件中对于 store 的某个 state 的更新,导致了 B 组件的重新渲染,有比较严重的性能问题。
于是我又重新阅读了文档,发现我之前对于 zustand 的使用是错误的。
错误用法 1 没有使用 single selector 或者 shallow 去获取 state
这是之前的写法以及对应的组件,useGlobalStore 中有不只 uploadToServerProgress, uploadStatus 两个 state。
当 uploadToServerProgress 或者 uploadStatus 更新的时候,UploadStateContainer 会重新渲染。(符合预期)
当 useGlobalStore 中的其他 state 更新的时候,UploadStateContainer 也会重新渲染。(不符合预期)
这是因为 const { uploadToServerProgress, uploadStatus } = useGlobalStore();
其实是解构赋值的简写,等价于
对于 react 来说,只要 globalStore 更新,就会导致 UploadStateContainer 重新渲染。因此我们需要改为以下写法:
写法 1 single selector
写法 2 使用 useShallow
错误用法 2 使用 selector 的时候颗粒度不够
cameraData 是通过订阅其他的服务获取的,内部包含包括相机图像、相机 id 等数据。其中相机图像是高频更新的数据。
如果这样写,虽然这里也是 single selector,但是当 cameraBase64 更新的时候,cameraData 会更新,CurrentCameraId 也会重新渲染。
因此这里还是遵循最小粒度原则,只获取需要的数据。
错误用法 3 使用了多个 store 去存储不同的 state,而不是使用 slice 把不同的 state 分组
在官方的文档中 Flux inspired practice - Zustand 提到,应该使用单一存储,而不是使用多个 store 去存储不同的 state。
Quote
Recommended patterns 推荐模式
Single store 单一存储
Your applications global state should be located in a single Zustand store.
你的应用程序的全局状态应该位于一个单一的 Zustand 存储中。
If you have a large application, Zustand supports splitting the store into slices.
如果你有一个大型应用程序,Zustand 支持将存储拆分为切片。
错误用法 4 与 UI 无关的 state 通过 selector 获取
在一个组件中,我有一个 handleSave 的方法,调用接口保存数据。
我之前的写法是,在组件 A 内部,使用 single selector 获取需要的数据,然后调用接口保存数据。
但是这样的写法是错误的。
在组件 B 中,我通过操作改变了 state1,但是由于我在 A 中获取了 state1,state1 的变化会导致 A 组件重新渲染。
正确的做法是,直接在 handleSave 方法内部访问 store,而不是通过 selector 将状态传递给它。
参考
master 分支下的 notes/zustand 学习笔记.md --- notes/zustand学习笔记.md at master · puxiao/notes