使用 useSyncExternalStore 构建自定义存储
从头实现一个轻量级外部存储,并使用 useSyncExternalStore 将其连接到 React。
使用 useSyncExternalStore 构建自定义存储 是 CoddyKit 上的免费 React Academy 课时。 这是第 4 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 React Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 React Academy 课程共包含 4 节课。
存储库的最小要求
自定义存储库需要三样东西:一些状态、一个用于注册监听器的订阅方法,以及一个用于读取当前状态的 getSnapshot 方法。这就是 useSyncExternalStore 所需的完整契约。
将存储库保持得如此精简,可以使它与框架无关,因此同一个存储库既可以在 React 内部使用,也可以在 React 外部使用。
一个 createStore 工厂
createStore 工厂接受一个初始值,并返回一个包含 getSnapshot、订阅方法和更新方法的对象。它在内部保存当前状态以及一组监听器回调。
这种工厂模式让您可以通过一个可复用函数创建多个相互独立的存储库。
更新函数通知订阅者
更新操作改变状态时,会设置新值,然后调用每个已注册的监听器。这些监听器就是 React 通过订阅函数提供的回调。
调用这些回调会告诉 React 存储库发生了变化,促使它重新读取 getSnapshot,并重新渲染所有读取该存储库的组件。
通过钩子连接到 React
组件通过调用 useSyncExternalStore,并传入存储库的订阅方法和 getSnapshot 方法,来读取存储库。该钩子返回当前值,并在值发生变化时重新渲染。
您可以将这套逻辑封装成 useStore 这样的自定义钩子,使组件每次只需调用一个函数,而不必自行连接这些钩子参数。
无需提供者即可在组件间共享
由于存储库是模块级对象,任何导入它的组件都会共享同一份状态,无需使用上下文提供者。您不需要包裹组件树,也不需要逐层传递属性。
这正是外部存储的重要吸引力之一:通过扁平的导入即使用模式共享全局状态,而不是构建提供者层级。
为不同状态切片使用多个存储库
您可以创建多个小型存储库,分别管理状态的一个切片,而不是使用一个庞大的单体存储库。组件只订阅自己关注的状态切片。
这样可以分离关注点并减少重新渲染,因为一个切片发生变化时,读取另一个切片的组件完全不会受到影响。
Zustand 在内部使用它
Zustand 是一个流行的极简状态库,完全基于这种模式构建,并从第 4 版起在内部使用 useSyncExternalStore。它简洁的接口本质上是经过完善的 createStore,再加上一层选择器。
了解这种联系后,您就能更清楚地看待这类库:它们只是围绕同一基础原语构建的轻量、易用封装,而您也可以自行构建这个原语。
仅在切片发生变化时重新渲染
通过向 getSnapshot 传入一个只返回组件所使用状态部分的选择器,可以确保组件仅在该部分发生变化时重新渲染。
这要求选择器返回稳定的结果,因此请对派生值进行记忆化,以避免新引用导致的无限循环,同时仍将更新限定在相关切片内。
开发者工具调试标签
为了调试,您可以为存储附加标签并记录更新日志,或者与浏览器开发者工具集成,以便追踪哪个存储在何时发生了变化。
即使是在 update 中加入一个由开发标志控制的简单控制台日志,也能帮助您在构建存储时理解状态流转。
在 React 内外测试存储
由于存储是普通的 JavaScript,您可以直接测试其逻辑:调用更新并断言 getSnapshot 返回新值,而无需渲染任何内容。
您也可以在 React 中测试它:渲染一个从存储读取数据的组件,并验证调用更新后是否发生重新渲染,从而同时覆盖存储及其集成。
快速检查:自定义存储的订阅函数
请回顾自定义存储订阅方法所遵循的约定。
回顾:构建自定义存储
自定义存储需要状态、订阅和 getSnapshot。通过 createStore 工厂和一个通知监听器的更新函数,可以在无需提供者组件的情况下实现共享的全局状态,因为模块导入共享同一个实例。
请使用多个切片存储和选择器来限制重新渲染,并记住引用必须保持稳定。Zustand v4+ 正是基于这一模式构建的,而这种纯 JavaScript 存储在 React 内外都很容易测试。
常见问题解答
「使用 useSyncExternalStore 构建自定义存储」课时是免费的吗?
是的 — 「使用 useSyncExternalStore 构建自定义存储」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 React Academy 课程的其余内容,请升级到 CoddyKit PRO。 React Academy 课程共包含 4 节课。
「使用 useSyncExternalStore 构建自定义存储」这节课中我会学到什么?
从头实现一个轻量级外部存储,并使用 useSyncExternalStore 将其连接到 React。 你通过在浏览器中直接运行的动手代码来练习 React Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 React Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 React Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 4 节课,共 4 节。
「使用 useSyncExternalStore 构建自定义存储」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 React Academy 课中编写并运行代码吗?
能。每节 React Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。
此课程中的所有课时
- 外部存储订阅的问题
- useSyncExternalStore API 与参数
- 订阅浏览器 API
- 使用 useSyncExternalStore 构建自定义存储