React读取localStorage未触发正确重渲染,登录后仍显示登录页
问题根源
- 登录状态初始化逻辑直接写在组件渲染流程中,渲染阶段调用
setLoggedIn、setUserID这类状态更新方法会触发组件重渲染,而你定义的模块级全局变量checkedLogin会在第一次渲染执行后被永久标记为true,重渲染时不会再次执行初始化赋值逻辑,最终isLoggedIn保持初始的false值,所以一直渲染登录页。 - 模块级全局变量
checkedLogin不会随组件卸载重置,只要页面不刷新,后续组件重新挂载时永远不会再执行初始化登录校验,逻辑存在缺陷。 - 读写localStorage时格式不统一:存储时用
JSON.stringify把数字转成了字符串,读取时用parseInt虽然可以兼容,但存在类型转换错误的风险。
修复方案
把初始化登录校验逻辑放到useEffect钩子中执行,这是React官方推荐的组件初始化副作用逻辑写法,不需要额外的全局变量防止重复执行。
修复后的完整代码如下:
import React, { useState, useEffect } from 'react'; import Login from '../Login/Login'; import GroupList from '../GroupList/GroupList'; function App(props) { // 状态定义 const [isLoggedIn, setLoggedIn] = useState(false); const [userID, setUserID] = useState(null); // 组件挂载时执行一次登录状态校验 useEffect(() => { if("userID" in localStorage) { // 读写格式统一,避免类型错误 const newUserID = JSON.parse(localStorage.getItem("userID")); loginComplete(newUserID); } }, []); // 空依赖数组保证只在组件挂载时执行一次 // 登录完成回调,更新应用状态 function loginComplete(newUserID) { setLoggedIn(true); setUserID(newUserID); // 持久化存储到localStorage localStorage.setItem('userID', JSON.stringify(newUserID)); } console.log(userID); console.log(isLoggedIn); // 按登录状态渲染对应页面 if(isLoggedIn) { return <GroupList API_ROUTE={props.API_ROUTE} userID={userID} /> }else{ return <Login API_ROUTE={props.API_ROUTE} loginCallback={loginComplete} /> } } export default App;
内容的提问来源于stack exchange,提问作者Sean Holloway
相关产品推荐
相关产品推荐

