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

localStorage存在值但React AuthContext中user为null引发报错

问题原因

你的代码崩溃是因为组件首次渲染时,AuthContext里的user还是初始值null,这时候直接访问user.username就会抛出"Cannot read properties of null"的错误。虽然之后useEffect会从localStorage加载用户信息并更新state,但首次渲染的瞬间错误已经触发了。

解决方案

有三种简单的修复方式,选一种就行:

1. 使用可选链操作符(推荐)

直接在访问username前加?.,当user为null/undefined时会直接返回undefined,不会报错:

const Home = () => {
    const { user } = useAuthContext()
    
    return (
        <div>
            <Container>
                <Routes>
                    <Route
                        path="/"
                        element={user?.username === "admin" ? <Dashboard title="Dashboard" user="User" /> : <Navigate to="/login" />}
                    />
                </Routes>
            </Container>
        </div>
    )
}

2. 先判断user是否存在

在访问user.username之前,先确认user不是null:

const Home = () => {
    const { user } = useAuthContext()
    
    return (
        <div>
            <Container>
                <Routes>
                    <Route
                        path="/"
                        element={user && user.username === "admin" ? <Dashboard title="Dashboard" user="User" /> : <Navigate to="/login" />}
                    />
                </Routes>
            </Container>
        </div>
    )
}

3. 添加加载状态(更严谨)

如果想在用户信息加载完成前显示加载提示,可以给AuthContext加上loading状态:
首先修改AuthContextProvider:

export const authReducer = (state, action) => {
     switch (action.type) {
          case 'LOGIN':
               return { user: action.payload, isLoading: false }
          case 'LOGOUT':
               return { user: null, isLoading: false }
          case 'SET_LOADING':
               return { ...state, isLoading: action.payload }
          default:
               return state
     }
}

export const AuthContextProvider = ({ children }) => {
     const [state, dispatch] = useReducer(authReducer, {
          user: null,
          isLoading: true // 新增初始加载状态
     })

     useEffect(() => {
          const user = JSON.parse(localStorage.getItem('user'))

          if(user){
               dispatch({type: 'LOGIN', payload: user})
          } else {
               dispatch({type: 'SET_LOADING', payload: false})
          }
     },[])

     return (
          <AuthContext.Provider value={{ ...state, dispatch }}>
               {children}
          </AuthContext.Provider>
     )
}

然后在Home组件里先判断加载状态:

const Home = () => {
    const { user, isLoading } = useAuthContext()
    
    if(isLoading){
        return <div>加载中...</div>
    }
    
    return (
        <div>
            <Container>
                <Routes>
                    <Route
                        path="/"
                        element={user?.username === "admin" ? <Dashboard title="Dashboard" user="User" /> : <Navigate to="/login" />}
                    />
                </Routes>
            </Container>
        </div>
    )
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 19:02:11