1. React 状态持久化深度解析:为何 Redux 与 LocalStorage 必须并存?
在构建现代 React 应用时,Token 管理是每个前端开发者都会遇到的"必修课"。很多新手开发者常常困惑:明明已经在 Redux 中存储了 Token,为什么页面刷新后用户仍然需要重新登录?这个问题看似简单,实则涉及 React 状态管理的核心机制。本文将带你深入理解 Redux 和 LocalStorage 的本质区别,并构建一套完整的持久化解决方案。
1.1 内存与磁盘的博弈:响应式 vs 持久化
要理解这个问题,我们需要先明确两种存储机制的本质差异:
Redux(内存状态管理)
- 运行在 JavaScript 执行内存(RAM)中
- 核心优势:响应式(Reactivity)
- 状态变更自动触发组件重新渲染
- 生命周期:随页面刷新/关闭而重置
LocalStorage(磁盘持久化存储)
- 浏览器提供的 Web Storage API
- 数据实际存储在本地磁盘(ROM)中
- 核心优势:持久性(Persistence)
- 生命周期:页面刷新/浏览器重启后依然存在
提示:Redux 就像你的工作台,所有工具都放在手边方便取用;LocalStorage 则是你的储物柜,东西放进去不会轻易丢失。
1.1.1 单一存储方案的致命缺陷
仅使用 Redux:
- 页面刷新后内存状态重置
- Token 丢失导致用户被迫重新登录
- 用户体验极差(特别是填写表单中途刷新)
仅使用 LocalStorage:
- 数据变更无法触发视图更新
- 用户登出后,界面可能仍显示登录状态
- 状态不一致导致各种诡异 Bug
1.2 Hooks 的执行限制:为什么不能在非组件文件中使用 useSelector
很多开发者尝试在请求拦截器(如 axios.interceptors)中直接使用 useSelector 获取 Token,结果遇到 "Invalid hook call" 错误。这背后是 React Hooks 的核心设计原则。
1.2.1 Hooks 的调用规则
React 严格规定 Hooks 只能在以下两种情况下调用:
- 函数组件的顶层作用域
- 自定义
