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

Redux环境下登录后无法跳转至Logout组件问题排查

问题分析与修复方案

核心问题梳理

  1. 状态管理逻辑混乱:登录时直接覆盖users数组为单个用户对象,导致Logout组件中users.map()调用失败(对象无法执行数组方法),页面空白无报错。
  2. 登录状态判断错误:App组件以users.email作为登录判断依据,但初始users是数组,登录后变为对象,逻辑完全不成立。
  3. Logout动作破坏数据:将users设为null,导致后续Form组件调用users.find()报错。
  4. 缺少用户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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 13:22:27