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

React组件传值异常:点击卡片详情始终显示数组最后一项

问题修复方案

核心问题分析

你当前的代码在electronics.map循环里为每个卡片都渲染了一个ShowDetails组件,所有弹窗共用同一个modalShow状态。当点击任意卡片的按钮时,所有弹窗都会被触发显示,而DOM中最后一个弹窗会覆盖前面的,所以始终看到数组最后一项的内容。

修改后的代码

Electronic卡片组件

import { useState } from "react";
import { Button } from "react-bootstrap";
import { Card } from "react-bootstrap";
import { useSelector } from "react-redux";
import ShowDetails from "./ShowDetails";

export default function Electronic() {
  const electronics = useSelector((state) => state.productReducer);
  const [modalShow, setModalShow] = useState(false);
  // 新增状态存储当前选中的商品
  const [selectedProduct, setSelectedProduct] = useState(null);

  return (
    <>
      <center dir="rtl">
        <br></br>
        <br></br>
        <br></br>
        <br></br>
        {electronics.map((item) => (
          <Card
            key={item.id} // 添加唯一key,避免React渲染警告
            style={{
              width: "18rem",
              display: "inline-block",
              backgroundColor: "white",
              textAlign: "center",
              borderColor: "#fade0f",
              margin: 5,
            }}
          >
            <Card.Img
              variant="top"
              src={item.product_image}
              style={{ width: 100, height: 100 }}
            />
            <Card.Body>
              <Card.Title dir="rtl">{item.name}</Card.Title>
              <Button
                style={{ backgroundColor: "#fade0f", borderColor: "#fade0f", color: "black" }}
                variant="primary"
                onClick={() => {
                  // 点击时选中当前商品并打开弹窗
                  setSelectedProduct(item);
                  setModalShow(true);
                }}
              >
                פרטים
              </Button>
            </Card.Body>
          </Card>
        ))}
        <br></br>
        <br></br>
        <br></br>
        <br></br>
      </center>
      {/* 将弹窗移到循环外,只渲染一个实例 */}
      <ShowDetails
        products={selectedProduct}
        show={modalShow}
        onHide={() => {
          setModalShow(false);
          // 关闭弹窗时清空选中的商品
          setSelectedProduct(null);
        }}
      />
    </>
  );
}

ShowDetails详情弹窗组件

import { useState } from "react";
import { Image } from "react-bootstrap";
import Button from "react-bootstrap/Button";
import Modal from "react-bootstrap/Modal";

export default function ShowDetails(props) {
  const [amount, setAmount] = useState(1);

  // 无选中商品时不渲染弹窗
  if (!props.products) return null;

  return (
    <>
      <Modal
        {...props}
        size="sm"
        aria-labelledby="contained-modal-title-vcenter"
        centered
        style={{ textAlign: "center" }}
        animation={true}
      >
        <Modal.Header closeButton></Modal.Header>

        <Modal.Body dir="rtl">
          <Image
            variant="top"
            src={props.products.product_image}
            style={{ width: 200, height: 200 }}
          />
          <Modal.Title id="contained-modal-title-vcenter" style={{ textAlign: "center" }}>
            {props.products.name}
          </Modal.Title>
          <h5>{props.products.description}</h5>
          <h4>{props.products.price * amount} ₪</h4>

          <Button
            style={{ backgroundColor: "#fade0f", borderColor: "#fade0f", color: "black" }}
            onClick={() => {
              setAmount(Math.max(1, amount - 1));
            }}
          >
            -
          </Button>
          <h4 style={{ display: "inline-block", margin: 10 }}>{amount}</h4>
          <Button
            style={{ backgroundColor: "#fade0f", borderColor: "#fade0f", color: "black" }}
            onClick={() => {
              setAmount(Math.min(props.products.qty, amount + 1));
            }}
          >
            +
          </Button>
          <br></br>
          <br></br>
          <Button
            style={{
              backgroundColor: "#fade0f",
              borderColor: "#fade0f",
              color: "black",
              width: 200,
            }}
            onClick={() => {
              setAmount(1);
            }}
          >
            הוספה לסל
          </Button>
        </Modal.Body>
      </Modal>
    </>
  );
}

关键修改点

  • 移除循环内的ShowDetails组件,改为在循环外仅渲染一个弹窗实例,避免重复创建弹窗导致的覆盖问题。
  • 新增selectedProduct状态存储当前点击的商品,确保弹窗渲染对应的数据。
  • 点击按钮时同时设置选中商品和弹窗显示状态,关闭弹窗时清空选中状态。
  • 为循环中的Card添加唯一key,符合React列表渲染规范。

内容的提问来源于stack exchange,提问作者abcdefg

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 07:15:27