将状态与 localStorage 同步
构建 useLocalStorage 自定义钩子,让 React 状态与 localStorage 双向同步。
将状态与 localStorage 同步 是 CoddyKit 上的免费 React Academy 课时。 这是第 2 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 React Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 React Academy 课程共包含 4 节课。
朴素方案会逐渐失去同步
最初的想法可能是,在一个位置读取 localStorage,在另一个位置写入,但两者可能逐渐不一致。忘记持久化的状态更新,或未反映到状态中的持久化值,都会导致错误。
您需要一个单一事实来源,让 React 状态与存储始终保持同步。
useLocalStorage 自定义钩子
简洁的解决方案是使用 useLocalStorage 钩子封装 useState,并自动持久化更改。它会像 useState 一样返回值和设置函数。
使用者可以像使用普通状态一样使用它,同时无需额外操作就能获得持久化能力。
惰性初始化函数
读取 localStorage 是同步操作,因此不应在每次渲染时执行。请将一个函数传给 useState,也就是使用惰性初始化函数,这样读取操作只会在挂载时执行一次。
在该函数中解析已存储的值,或者返回提供的默认值。
惰性初始化为何重要
如果直接将初始状态计算结果作为参数传入,即使该结果在第一次渲染后会被忽略,其中的表达式仍会在每次渲染时执行。传入函数后,React 只会调用它一次。
对于 localStorage 读取,这可以避免每次渲染都重复执行同步的主线程操作。
通过 useEffect 同步
要持久化更新,请添加一个 useEffect,使其在值发生变化时运行,并调用 localStorage.setItem(key, JSON.stringify(value))。
将该值放入依赖数组后,每次状态变化都会自动写入存储。
使用函数式更新避免陈旧闭包
根据前一个值进行设置时,请使用函数式写法 setValue(prev => prev + 1)。这样可以避免陈旧闭包导致写入旧的捕获值。
对于可能捕获过时快照的事件处理程序和副作用,这一点尤其重要。
处理空的已存储值
getItem 在键不存在时会返回 null。您的初始化函数必须检测这种情况,并回退到默认值,而不是尝试解析空值。
像 stored != null ? JSON.parse(stored) : defaultValue 这样的保护条件可以妥善处理首次访问。
TypeScript 泛型
在 TypeScript 中,您可以将钩子设为泛型:function useLocalStorage<T>(key: string, initial: T)。这样可以保留值的类型,让使用者获得完整的类型安全保障。
返回的元组类型为 [T, Dispatch<SetStateAction<T>>],与 useState 保持一致。
存储数据的版本管理
随着时间推移,数据结构会发生变化,旧的存储值可能导致新代码出错。请在数据旁边存储版本键,以便检测过时的格式。
例如,保存 { version: 2, data },并在读取时比较版本号。
版本不匹配时清除数据
当存储的版本与当前版本不匹配时,请丢弃或迁移旧值,而不要直接信任它。最简单的策略是移除过时的条目,并回退到默认值。
这样可以避免应用程序的新版本因旧版本写入的数据而崩溃。
组合完整的钩子
完整的 useLocalStorage 会将安全读取并解析的惰性初始化函数、支持函数式更新的设置函数,以及通过版本管理写入数据的 useEffect 组合起来。
最终得到的是一个可直接替换 useState 的实现,并且能够在重新加载后保留数据。
快速检查
检验您对状态初始化的理解。
回顾
您学习了如何构建带有惰性初始化函数的 useLocalStorage 钩子,如何通过 useEffect 持久化更改,如何使用函数式更新避免陈旧闭包,以及如何处理空值。
您还了解了 TypeScript 泛型和版本管理,以便安全地清除过时数据。
常见问题解答
「将状态与 localStorage 同步」课时是免费的吗?
是的 — 「将状态与 localStorage 同步」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 React Academy 课程的其余内容,请升级到 CoddyKit PRO。 React Academy 课程共包含 4 节课。
「将状态与 localStorage 同步」这节课中我会学到什么?
构建 useLocalStorage 自定义钩子,让 React 状态与 localStorage 双向同步。 你通过在浏览器中直接运行的动手代码来练习 React Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 React Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 React Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 2 节课,共 4 节。
「将状态与 localStorage 同步」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 React Academy 课中编写并运行代码吗?
能。每节 React Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。
此课程中的所有课时
- 在 React 中读取和写入 localStorage
- 将状态与 localStorage 同步
- 处理跨标签页的存储事件
- sessionStorage、IndexedDB 与 API 选择