跳到主要内容

认识

2023年01月12日
柏拉文
越努力,越幸运

一、认识


Zustand 官网

Zustand 相较于 React-Redux 的优势在于其极简且直观的 API 设计,无需繁琐的 actionreducer 和中间件配置, 无需繁杂的样板代码, 通过闭包和订阅机制实现了精准更新, 确保组件只在真正需要时才重新渲染, 同时支持状态切片和选择器,使得组件能够只订阅所需数据。再加上与 React 18useSyncExternalStore 无缝衔接, 能够在并发模式下保持数据一致性和高性能, 借助 useSyncExternalStore 与选择器使组件仅订阅所需状态,从而减少不必要的重渲染。同时它不依赖于 React Context,避免了大规模状态更新时的性能瓶颈,使用起来更符合现代 React Hooks 编程风格,学习曲线更低,适用于从小型到大型应用,而 Redux 尽管拥有丰富的生态系统和强大的中间件支持,但往往需要更多样板代码和复杂的架构来管理状态。

useSyncExternalStoreReact 18 引入的一个内置 Hook, 专门用于解决外部数据源(比如 Redux``、Zustand 等状态管理库)与 React 组件之间的数据同步问题。它的主要作用是让组件在渲染期间能够安全、一致地读取外部 store 的状态快照, 同时在 store 发生变化时,自动触发组件重新渲染,从而确保 UI 始终与外部状态保持同步。具体来说,它需要你提供两个核心函数:

  • subscribe: 一个函数, 接收一个单独的 callback 参数并把它订阅到 store 上。当 store 发生改变时会调用提供的 callback,这将导致 React 重新调用 getSnapshot 并在需要的时候重新渲染组件。subscribe 函数会返回清除订阅的函数。换句话说: subscribe 的作用就是让每个使用 store 的组件都能注册自己的订阅回调。当 store 更新时, 我们手动调用订阅回调, 从而让相应的组件通过 getSnapshot 获取最新状态并触发重新渲染。所以 subscribe 注册的回调数目实际上就反映了当前有多少组件(或其他订阅者)在关注这个 store 的变化,同时它也支持取消订阅以避免不必要的更新。

  • getSnapshot: 一个函数,返回组件需要的 store 中的数据快照。在 store 不变的情况下,重复调用 getSnapshot 必须返回同一个值。如果 store 改变,并且返回值也不同了(用 Object.is 比较),React 就会重新渲染组件。

  • 返回值: 该 store 的当前快照,可以在你的渲染逻辑中使用。

Zustandcreate 实现逻辑基于 useSyncExternalStore, 通过 subscribe 参数来收集所有订阅该 Store 的组件的通知更新回调。通过 getSnapshot 来传递给 store 当前数据状态。当修改 store 数据后, 会循环遍历订阅 Store 的组件通知更新回调, React 会重新调用 getSnapshot , 并通过 Object.is 来比较前后状态, 如果发生变化, 在需要的时候重新渲染组件。因此, Zustandcreate 通过 useSyncExternalStore subscribe 与 getSnapshot 的结合, 实现组件对外部状态的精准订阅和更新, 从而构建出一个轻量高效且易于扩展的状态管理解决方案。

二、问题