You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从localStorage获取用户信息并解决首次渲染无数据问题

登录后首次渲染Navbar无法获取用户信息,刷新后恢复正常

问题详情

登录后首次渲染Navbar组件时,拿不到当前用户的username和_id,导航栏没法显示用户名,点个人资料的跳转链接也没用;但刷新页面后就能正常获取信息。

相关代码

const Navbar = () => {
  const {user} = useSelector((state) => state.user)
  const user2 = JSON.parse(user).username
  const id = JSON.parse(user)._id

return (
    <Typography marginRight={2} sx={{color: {xs: 'white', md: 'black'}}}> Hello  
    {user2}  </Typography>

    <Link to={`/edit_user/${id}`} style={{textDecoration: 'none', color: 
         'inherit'}}>
      <MenuItem onClick={handleCloseUserMenu}>
              {settings[0]}
            </MenuItem>
     </Link>
      )
}

userSlice.js

import {createSlice} from '@reduxjs/toolkit'

const user = localStorage.getItem("token")

export const userSlice = createSlice({
  name: 'user',
  initialState : {
    user: user ? user : null,
    isError: false,
    isSuccess: false,
    isLoading: false,
    message: ''
  },
  reducers: {getUserStart: (state) =>{
      state.isLoading = true;
      state.isError = false;
    },
    getUserSuccess:(state, action) =>{
      state.isLoading = true;
      state.isSuccess = true;
      state.user = action.payload;
    },
    getUserFailure: (state, action) =>{
      state.isLoading = false;
      state.isError = true;
      state.message = action.payload
      state.user = null
    }
  }

})

apiCalls.js

export const getUser = async (dispatch,id) =>{
       getUserStart()
       try {
            const getUser = await publicRequest.get('/users/find/'+id)
            dispatch(getUserSuccess(getUser.data))
        } catch (error) {
            dispatch(getUserFailure())
        }
    }
export const loginUser = async (userData, dispatch) =>{
    dispatch(loginStart())
    try {
        const res = await publicRequest.post('/auth/login', userData)
        localStorage.setItem('token', JSON.stringify(res.data))
        dispatch(loginSuccess(res.data))
    } catch (error) {
        const message = "Wrong Username or Email "
        dispatch(loginFailure(message))
    }
}

问题现象

  • localStorage内容:已存储包含username和_id的用户信息
  • 首次渲染结果:导航栏没显示用户名,个人资料跳转链接无效
  • 刷新后结果:导航栏正常显示用户名,跳转链接可正常访问

解决办法

1. 修正redux初始状态的存储格式

你现在userSlice里初始状态直接存了localStorage拿的字符串,但登录成功后存的是对象,这就导致首次登录后redux里的user是对象,Navbar里强行JSON.parse对象肯定报错。改一下userSlice的初始状态:

const user = localStorage.getItem("token")
export const userSlice = createSlice({
  name: 'user',
  initialState : {
    // 把字符串解析成对象再存
    user: user ? JSON.parse(user) : null,
    isError: false,
    isSuccess: false,
    isLoading: false,
    message: ''
  },
  // 其他代码不变
})

2. Navbar里加空值判断,避免报错

万一user还没加载出来(比如登录请求还在pending),直接取属性会崩,加个可选链操作符:

const Navbar = () => {
  const {user} = useSelector((state) => state.user)
  const username = user?.username || ''
  const userId = user?._id || ''

  return (
    <Typography marginRight={2} sx={{color: {xs: 'white', md: 'black'}}}> 
      Hello {username}  
    </Typography>

    {/* 只有userId存在时才渲染链接 */}
    {userId && (
      <Link to={`/edit_user/${userId}`} style={{textDecoration: 'none', color: 'inherit'}}>
        <MenuItem onClick={handleCloseUserMenu}>
          {settings[0]}
        </MenuItem>
      </Link>
    )}
  )
}

3. 修正userSlice里的状态错误

你看getUserSuccess里把isLoading设成true了,这明显不对,请求成功后应该把loading关掉:

getUserSuccess:(state, action) =>{
  state.isLoading = false; // 这里改成false
  state.isSuccess = true;
  state.user = action.payload;
},

4. 确认所有action都导出了

别漏了导出loginStart这些action,不然apiCalls里调用会报错:

export const { getUserStart, getUserSuccess, getUserFailure, loginStart, loginSuccess, loginFailure } = userSlice.actions

内容的提问来源于stack exchange,提问作者Stykgwar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 14:36:35