Firebase登录后localStorage的isLoggedIn值为undefined的原因及修复
问题:登录后isLoggedIn值为undefined,路由无法正常工作
我通过官方文档学习Firebase,已实现谷歌账号和邮箱密码登录功能。点击登录按钮时dispatch setLogInValue action,状态虽有更新,但isLoggedIn的值变为undefined;首次访问页面时该值为null。期望登录后isLoggedIn为true并跳转到首页,但由于该值为undefined,路由功能无法正常工作。
相关代码见下文,核心问题出在状态更新与localStorage的交互逻辑中:
核心原因分析
localStorage.setItem返回值导致赋值错误:在slice的setLogInValuereducer中,直接将localStorage.setItem的返回值赋值给了state.email和state.isLoggedIn。但setItem方法无返回值(即返回undefined),这直接导致状态字段被设置为undefined。- localStorage存储类型不匹配:localStorage仅支持存储字符串,初始获取
loggedInStatus时拿到的是字符串或null,未转换为布尔值,导致路由判断逻辑异常。
修复方案
1. 修正slice.js中的状态更新逻辑
修改setLogInValue reducer,先执行localStorage.setItem存储数据,再将正确值赋值给state,同时处理初始状态的类型转换:
import { createSlice } from '@reduxjs/toolkit'; // 初始状态处理:将localStorage的字符串转换为布尔值 const initialState = { email: localStorage.getItem('email') || null, // 若localStorage中有loggedInStatus且为"true",则isLoggedIn为true,否则为false isLoggedIn: localStorage.getItem('loggedInStatus') === 'true', }; export const slice = createSlice({ name: 'slice', initialState, reducers: { setLogInValue: (state, action) => { // 先存储到localStorage localStorage.setItem('email', action.payload); localStorage.setItem('loggedInStatus', 'true'); // 存储字符串类型的true // 再更新state state.email = action.payload; state.isLoggedIn = true; }, }, }); export const { setLogInValue } = slice.actions; export default slice.reducer;
2. 验证路由判断逻辑
App.jsx中的路由判断逻辑无需修改,修复后isLoggedIn会是标准布尔值true/false,可正常触发路由切换:
const { isLoggedIn } = useSelector(state => state.info); console.log('App:', isLoggedIn); // 现在会输出true/false
3. (可选)优化Login组件跳转时机
Redux Toolkit的dispatch是同步操作,修复后直接在dispatch后执行navigate即可确保状态更新:
// 谷歌登录回调示例 signInWithPopup(auth, provider) .then(result => { const user = result.user; dispatch(setLogInValue(user.email)); navigate('/', { replace: true }); })
效果验证
修复后:
- 首次访问页面时,
isLoggedIn为false,路由自动跳转到登录页 - 登录成功后,
isLoggedIn被设置为true并同步存储到localStorage,页面跳转至首页 - 刷新页面时,初始状态会从localStorage读取字符串"true"并转换为布尔值
true,保持登录状态
内容的提问来源于stack exchange,提问作者Mahbubul Hasan
相关产品推荐
相关产品推荐

