React useEffect搭配useState出现无限循环及侧边栏需刷新显示问题求助
问题原因
你修改后useEffect依赖为空数组,仅会在根组件首次挂载时执行一次鉴权请求。登录操作成功后仅更新了localStorage,没有同步更新全局Context中的authState,路由跳转不会触发根组件重新挂载,authState.status一直为初始的false,因此侧边栏不会显示,只有手动刷新页面重新触发鉴权请求才能更新状态。
修复步骤
- 登录成功后同步更新全局状态
在你的登录页(Auth组件)登录接口请求成功的回调中,获取Context的setAuthState方法,直接更新全局状态,不需要等待鉴权接口二次获取:
// Auth组件内的登录请求逻辑 const { setAuthState } = useContext(AuthContext); const handleLogin = async () => { const res = await axios.post('你的登录接口地址', 登录参数, {withCredentials: true}); if (!res.data.error) { // 同步更新全局状态 setAuthState({ username: res.data.username, id: res.data.id, status: true }); // 同步更新localStorage localStorage.setItem('user', res.data.username); // 登录成功后跳转到/users history.push('/users'); } }
- 优化根组件的鉴权useEffect逻辑
你当前根组件的useEffect中更新状态时引用了外部的authState,存在闭包隐患,改成函数式更新即可不需要把authState加入依赖数组,也不会触发无限循环:
useEffect(() => { axios.get('http://localhost:4000/users/auth/v', {withCredentials: true}).then((res) => { if (res.data.error) { // 用函数式更新,拿最新的prev状态修改,不需要依赖外部authState setAuthState(prev => ({ ...prev, status: false })); } else { setAuthState({ username: res.data.username, id: res.data.id, status: true }); localStorage.setItem('user', res.data.username); } }); },[setAuthState]);
- 优化侧边栏状态来源
侧边栏不要单独读取localStorage,直接用Context的状态,避免两者不同步:
// 删掉原来的localStorage读取,替换成下面的 const { authState } = useContext(AuthContext); const userData = authState.username;
- 退出登录同步清理状态
在Logout组件中,退出操作执行后同步重置全局authState和清空localStorage:
const { setAuthState } = useContext(AuthContext); const handleLogout = () => { // 调用退出接口后执行 setAuthState({ username: "", id: 0, status: false }); localStorage.removeItem('user'); history.push('/'); }
修改完成后,登录、退出、路由跳转时全局状态都会实时更新,不需要手动刷新页面就能正常显示/隐藏侧边栏。
内容的提问来源于stack exchange,提问作者madmeatballs
相关产品推荐
相关产品推荐

