Redux环境下登录后无法跳转至Logout组件问题排查
问题分析与修复方案
核心问题梳理
- 状态管理逻辑混乱:登录时直接覆盖
users数组为单个用户对象,导致Logout组件中users.map()调用失败(对象无法执行数组方法),页面空白无报错。 - 登录状态判断错误:
App组件以users.email作为登录判断依据,但初始users是数组,登录后变为对象,逻辑完全不成立。 - Logout动作破坏数据:将
users设为null,导致后续Form组件调用users.find()报错。 - 缺少用户ID存储:预设用户无ID字段,无法实现展示用户ID的需求。
分步修复
1. 修正Reducer状态逻辑
改用loggedInUser字段管理登录状态,保留原有用户列表,同时给预设用户添加ID:
import {createStore} from 'redux'; const initialState={ users: [{ id: 1, // 为预设用户添加ID email:"user1@fireflink.com", password:"123" }], loggedInUser:null, // 专门存储当前登录用户 products:[{ id:1, name:'pen', price:10 },{ id:2, name:'pencil', price:5 },{ id:3, name:'Eraser', price:15 }], cart:[] } const reducer = (state=initialState,action) =>{ switch(action.type){ case "LOGIN": // 动作名改为LOGIN,语义更准确 return{ ...state, loggedInUser: action.payload // 存储匹配到的登录用户 } case "LOGOUT": return{ ...state, loggedInUser: null // 仅清空登录状态,保留原有用户列表 } default: return state; } } export default createStore(reducer)
2. 修正App组件的登录判断逻辑
基于loggedInUser判断是否登录,而非错误的users数组属性:
import "./App.css"; import Form from "./Components/Form"; import { useSelector } from "react-redux"; import Logout from "./Components/Logout"; function App() { const loggedInUser = useSelector((state) => state.loggedInUser); if (loggedInUser) { return <Logout />; } else { return <Form />; } } export default App;
3. 修正Form组件的登录逻辑
匹配到用户后,dispatchLOGIN动作设置loggedInUser,不再覆盖用户列表:
import { useState } from "react"; import "./Form.module.scss"; import { useDispatch, useSelector } from "react-redux"; export default function Form() { const [name, setName] = useState(""); const [email, setEmail] = useState(""); const [password, setPassword] = useState(""); const dispatch = useDispatch(); const users = useSelector((state) => state.users); const handleLogin = () => { const matchedUser = users.find( (user) => user.email === email && user.password === password ); if (matchedUser) { dispatch({ type: "LOGIN", payload: matchedUser // 传入完整用户对象(包含ID) }); } else { alert("try again"); } }; const handleSubmit =(e) =>{ e.preventDefault() } return ( <form className="border login__form" onSubmit={handleSubmit}> <h3>Login Form</h3> <hr /> <div className="mb-3"> <label htmlFor="exampleInputName1" className="form-label"> Name </label> <input type="text" className="form-control" id="exampleInputName1" aria-describedby="emailHelp" value={name} onChange={(e) => setName(e.target.value)} /> </div> <div className="mb-3"> <label htmlFor="exampleInputEmail1" className="form-label"> Email address </label> <input type="email" className="form-control" id="exampleInputEmail1" aria-describedby="emailHelp" value={email} onChange={(e) => setEmail(e.target.value)} /> <div id="emailHelp" className="form-text"> we will never share your email with anyone else. </div> </div> <div className="mb-3"> <label htmlFor="exampleInputPassword1" className="form-label"> Password </label> <input type="password" className="form-control" id="exampleInputPassword1" value={password} onChange={(e) => setPassword(e.target.value)} /> </div> <div className="mb-3 form-check"> <input type="checkbox" className="form-check-input" id="exampleCheck1" /> <label className="form-check-label" htmlFor="exampleCheck1"> Check me out </label> </div> <div className="d-grid gap-2"> <button className="btn btn-outline-danger" type="submit" onClick={handleLogin} > Submit </button> </div> </form> ); }
4. 修正Logout组件,展示当前登录用户信息
显示loggedInUser的ID、邮箱等信息,而非错误遍历所有用户:
import { useDispatch, useSelector } from "react-redux"; export default function Logout() { const products = useSelector((state) => state.products); const loggedInUser = useSelector((state) => state.loggedInUser); const dispatch = useDispatch(); return ( <div className="container mt-4"> Welcome <span className="user_name ms-2">{name || 'User'}</span> {/* 展示当前登录用户的ID和邮箱 */} <div className="mt-3"> <p>用户ID: {loggedInUser.id}</p> <p>邮箱: {loggedInUser.email}</p> </div> {/* 展示产品列表 */} <h4 className="mt-4">产品列表</h4> {products.map((product) => ( <div key={product.id} className="mt-2"> {product.name} - {product.price}元 </div> ))} <button className="btn btn-outline-danger mt-4" onClick={() => dispatch({ type: "LOGOUT" })} > Logout </button> </div> ); }
修复后效果
- 输入正确凭证后,正常跳转至
Logout组件,展示用户ID、邮箱及产品列表 - 输入错误凭证时弹出"try again"提示
- 点击Logout按钮返回登录表单,原有用户数据不会被破坏
内容的提问来源于stack exchange,提问作者Sougata Mukherjee
相关产品推荐
相关产品推荐

