React手动输入URL时Redux Toolkit状态丢失及路由保护优化问题
解决方案
1. 解决Redux状态刷新丢失问题
Redux状态默认存储在内存中,页面刷新或手动输入URL会清空状态,因此需要将核心认证信息持久化到localStorage,并在应用启动时自动恢复状态。
修改authSlice.js
import { createSlice, current } from '@reduxjs/toolkit'; // 从localStorage读取初始认证状态 const loadAuthState = () => { try { const serializedState = localStorage.getItem('authState'); if (!serializedState) { return { token: null, signupError: "", loginError: "", loading: false, loginLoading: false, userId: undefined }; } return JSON.parse(serializedState); } catch (err) { console.error('加载认证状态失败:', err); return { token: null, signupError: "", loginError: "", loading: false, loginLoading: false, userId: undefined }; } }; // 将核心认证状态保存到localStorage const saveAuthState = (state) => { try { const serializedState = JSON.stringify({ token: state.token, userId: state.userId }); localStorage.setItem('authState', serializedState); } catch (err) { console.error('保存认证状态失败:', err); } }; const authSlice = createSlice({ name: "auth", initialState: loadAuthState(), reducers: { registerToken: (state, { payload }) => { state.token = payload.accessToken; state.userId = payload.id; saveAuthState(state); }, loginToken: (state, { payload }) => { state.token = payload.accessToken; state.userId = payload.id; saveAuthState(state); console.log(current(state)); }, setLoading: (state, { payload }) => { state.loading = payload; }, setRegisterError: (state, { payload }) => { state.signupError = payload; }, setLoginError: (state, { payload }) => { state.loginError = payload; }, setLoginLoading: (state, { payload }) => { state.loginLoading = payload; }, setToken: (state, { payload }) => { state.token = payload; saveAuthState(state); console.log(current(state)); }, logoutToken: (state) => { state.token = null; state.userId = null; localStorage.removeItem('authState'); } } }); export const { registerToken, loginToken, setLoading, setRegisterError, setLoginError, setLoginLoading, setToken, logoutToken } = authSlice.actions; export default authSlice.reducer;
2. 优化AuthGuard避免错误重定向
应用初始化时状态从localStorage读取存在极短延迟,添加加载状态避免用户被错误跳转:
修改authGuard.js
import { useSelector } from 'react-redux'; import { Navigate, useLocation } from 'react-router-dom'; function AuthGuard({ children }) { const { userId, loading } = useSelector(state => state.authReducer); const location = useLocation(); // 加载中显示占位组件,替换为你的自定义加载UI if (loading) { return <div>加载中...</div>; } if (!userId) { // 保存当前访问路径,登录后跳转回来 return <Navigate to="/signin" state={{ from: location.pathname }} />; } return <> {children} </>; } export default AuthGuard;
3. 处理已登录用户访问登录页的跳转逻辑
修改Login组件,检测到用户已登录时自动跳转到上次访问页面或默认仪表盘:
改造Login组件核心逻辑
import { useSelector } from 'react-redux'; import { Navigate, useLocation } from 'react-router-dom'; function Login() { const { userId } = useSelector(state => state.authReducer); const location = useLocation(); // 优先使用之前保存的跳转路径,默认跳转到仪表盘 const targetPath = location.state?.from || '/dashboard'; // 已登录状态直接跳转 if (userId) { return <Navigate to={targetPath} replace />; } // 原有登录表单代码 return ( // 你的登录表单UI及逻辑 ); } export default Login;
4. 路由配置说明
当前路由配置无需修改:登录/注册页面不受AuthGuard保护,仪表盘下所有子路由均通过AuthGuard的MainLayout统一控制权限,符合需求。
内容的提问来源于stack exchange,提问作者jsBug
相关产品推荐
相关产品推荐

