React Redux Store未更新,登录状态切换功能异常求助
问题:React Redux登录状态更新后无法获取最新值,无法切换Header显示内容
我希望实现:用户未登录时,页面Header显示登录和注册链接;用户登录后,显示登出链接。通过React Redux存储用户登录状态,登录/登出时调用dispatch更新状态。调试发现action和reducer参数传递正常,但获取Store值时始终显示旧值,无法实现状态切换。
相关代码
Login组件代码
import React, { useEffect, useState } from 'react' import { useNavigate } from 'react-router-dom'; import Footer from '../footer/Footer'; import "./Login.css"; import { setUser } from '../../actions/index'; import { useDispatch } from 'react-redux'; import store from '../../store'; const Login = () => { const state = store.getState(); const userdata = Object.values(state); const sendUserstatus = useDispatch(); const [email, setEmail] = useState(''); const [password, setPassword] = useState(''); const handleEmailChange = (event) => { setEmail(event.target.value); } const handlePasswordChange = (event) => { setPassword(event.target.value); } const navigate = useNavigate(); const handleSubmit = async (event) => { event.preventDefault(); const res = await fetch("/signin", { method: "POST", headers: { "content-Type": "application/json" }, body: JSON.stringify({ email, password }) }) const data = res.json(); if (res.status === 400 || !data) { window.alert("invalid Credentials"); } else { sendUserstatus(setUser(true)); console.log(userdata, "login successful"); window.alert("Login Successful"); navigate("/") } } return ( <> <form method='POST' onSubmit={handleSubmit} className="login-form"> <label className="login-label"> Email: <input type="email" value={email} onChange={handleEmailChange} className="login-input" /> </label> <br /> <label className="login-label"> Password: <input type="password" value={password} onChange={handlePasswordChange} className="login-input" /> </label> <br /> <a href="#sfsd" className="forgot-password-link">Forgot password?</a> <br /> <button type="submit" className="login-button">Login</button> </form> <Footer></Footer> </> ) } export default Login
Reducer代码
const initialdata = false; export const truefalse = (state = initialdata, action) => { switch(action.type) { case "SET_TRUE": return state = true; case "SET_FALSE": return state = false; default: return state; } } var wpmdata = 0; export const setWpm = (state = wpmdata, action) => { switch(action.type) { case"SET_WPM": return wpmdata = action.paylod; default: return wpmdata; } } var Accuracy = 0; export const setAccuracy = (state = Accuracy, action) => { switch(action.type) { case"SET_ACCURACY": return Accuracy = action.Accuracy; default: return Accuracy; } } var userStatus = null; export const setUser = (state = userStatus, action) => { switch(action.type){ case "SET_USER": return userStatus = action.userStatus; default: return userStatus; } } var Toggle = null; export const setToggle = (state = Toggle, action) => { switch(action.type) { case "TOGGLE": return Toggle = action.Toggle default: return Toggle } }
Actions代码
export const setTrue = () => { return { type: "SET_TRUE", } } export const setFalse = () => { return { type: "SET_FALSE", } } export const setWpm = (val) => { return { type: "SET_WPM", paylod: val } } export const setAccuracy = (val) => { return { type: "SET_ACCURACY", Accuracy: val } } export const setUser = (val) => { console.log(val, "afsdf"); return { type: "SET_USER", userStatus: val } } export const setToggle = (val) => { return { type: "TOGGLE", Toggle: val } }
Root Reducer代码
import { truefalse, setAccuracy, setWpm, setUser, setToggle } from "./typingtestReducer"; import { combineReducers } from "redux"; const rootReducer = combineReducers({ truefalse, setWpm, setAccuracy, setUser, setToggle }) export default rootReducer
核心问题分析
- 直接调用
store.getState()无法响应状态更新:组件初始化时仅执行一次store.getState(),后续Redux状态变化不会触发组件重新渲染,导致获取的始终是旧值。 - Reducer违反纯函数原则:所有reducer依赖全局变量并直接修改,Redux无法检测到状态变化(Redux要求reducer必须返回新状态值,不能修改外部状态)。
- 状态更新后立即打印旧值:
dispatch是异步更新操作,调用后立即打印状态时,更新尚未完成。
修复方案
1. 用useSelector替代直接调用store.getState()
使用React-Redux的useSelector钩子订阅状态变化,组件会在状态更新时自动重新渲染并获取最新值:
// 修改Login组件 import { useDispatch, useSelector } from 'react-redux'; const Login = () => { // 获取最新用户状态 const userStatus = useSelector(state => state.setUser); const sendUserstatus = useDispatch(); // ...其他代码 // 监听状态变化打印最新值 React.useEffect(() => { console.log('当前用户状态:', userStatus); }, [userStatus]); }
2. 修复Reducer,遵循纯函数规则
移除全局变量,直接使用state参数,返回新状态值:
// 修正后的setUser reducer export const setUser = (state = null, action) => { switch(action.type){ case "SET_USER": return action.userStatus; default: return state; } } // 其他reducer同理修改 export const truefalse = (state = false, action) => { switch(action.type) { case "SET_TRUE": return true; case "SET_FALSE": return false; default: return state; } } export const setWpm = (state = 0, action) => { switch(action.type) { case "SET_WPM": return action.payload; // 修正拼写错误:paylod → payload default: return state; } }
3. 修正Action中的拼写错误
// 修正setWpm action的payload拼写 export const setWpm = (val) => { return { type: "SET_WPM", payload: val } }
4. Header组件中实现状态切换显示
import { useSelector, useDispatch } from 'react-redux'; import { setUser } from '../actions/index'; const Header = () => { const userStatus = useSelector(state => state.setUser); const dispatch = useDispatch(); const handleLogout = () => { dispatch(setUser(false)); } return ( <header> {!userStatus ? ( <> <a href="/login">登录</a> <a href="/register">注册</a> </> ) : ( <button onClick={handleLogout}>登出</button> )} </header> ); }
内容的提问来源于stack exchange,提问作者Dheeraj Kumar Yadav
相关产品推荐
相关产品推荐

