React页面刷新后如何保留useReducer与Context全局登录状态
登录状态持久化实现方案
你当前的全局状态仅存储在浏览器内存中,页面刷新时内存会被清空,状态自然就回到初始值。只需要对接浏览器自带的localStorage做状态双向同步即可解决,全程不需要改现有组件的业务逻辑。
这里用的是浏览器原生的持久化存储能力,不需要安装任何第三方依赖,数据会绑定当前网站域名存在用户浏览器中,直到主动清除。
先修复现有代码的隐藏bug
你当前的状态字段名不统一:
- 初始状态定义的字段是
currentUser - 但
LOG_IN、LOG_OUT的Reducer返回里用的是userEmail
如果不统一,后续读取用户信息时很容易出现值读不到的问题,需要先把字段统一成和初始状态一致的currentUser。
具体修改步骤
1. 调整状态初始化逻辑
修改Store.js(原GlobalContext文件),不再直接用硬编码的初始值启动Reducer,初始化时先从localStorage读取之前保存的状态,读不到就用默认的未登录初始值。
2. 自动同步状态到本地存储
加useEffect钩子,只要全局state有更新,就把最新的state序列化后存到localStorage里,不需要在每个dispatch的地方手动写存储逻辑。
3. 登出逻辑补充
后续做登出操作时,除了dispatch更新状态的动作,记得清空localStorage里保存的状态值,不然下次打开还是会自动读成已登录状态。
修改后的Reducer.js
const Reducer = (state, action) => { switch(action.type){ case 'LOG_IN': return { // 修正字段名,和初始状态保持一致 currentUser: action.payload.currentUser, loggedIn: action.payload.LoggedIn } case 'LOG_OUT': return { // 统一字段名 currentUser: action.payload.currentUser, loggedIn: action.payload.LoggedIn } default: return state; } } export default Reducer;
修改后的Store.js(原GlobalContext.js)
import React, {useReducer, createContext, useEffect} from 'react' import Reducer from './Reducer'; // 定义默认的未登录初始值 const defaultState = { loggedIn: false, currentUser: '' } // 惰性获取初始状态:仅在应用初始化时从本地存储读一次数据 const getInitialState = () => { const savedState = localStorage.getItem('appLoginState'); return savedState ? JSON.parse(savedState) : defaultState; } const Store = ({children}) => { // 用读取到的本地状态作为useReducer的初始值 const [state, dispatch] = useReducer(Reducer, undefined, getInitialState) // 全局状态更新时自动同步到本地存储 useEffect(() => { localStorage.setItem('appLoginState', JSON.stringify(state)) }, [state]) return ( <Context.Provider value={[state, dispatch]}> {children} </Context.Provider> ) } export const Context = createContext(defaultState) export default Store
实现效果
- 登录成功dispatch更新状态后,最新的登录态、用户信息会自动同步到浏览器本地
- 不管是刷新页面,还是关掉浏览器重新打开网站,初始化时会直接从本地读回上次保存的登录状态,不会回到未登录的初始值
- 你现有Login.js、Profile.js的业务逻辑完全不需要改动,只需要调整全局状态的封装层即可生效
内容的提问来源于stack exchange,提问作者HASEEB Ahmed
相关产品推荐
相关产品推荐

