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

React电商网站出现「两个子元素key重复」报错求助

React购物车组件「Encountered two children with the same key」错误解决

问题描述

开发电商网站的CartScreen组件时,渲染购物车列表触发了「Encountered two children with the same key」错误,核心代码如下:

import React, {useEffect} from 'react'
import { Link, useParams, useNavigate, useLocation, useSearchParams } from 'react-router-dom' 
import { useDispatch, useSelector } from 'react-redux'
import { Row, Col, ListGroup, Image, Form, Button, Card} from 'react-bootstrap'
import Message from '../components/Message'
import { addToCart } from '../actions/cartActions'

export default function CartScreen() {
  const { id} = useParams()
  const { search } = useLocation();
  const [searchParams] = useSearchParams();
  const dispatch = useDispatch();
  
  const productID = id;
  const qty = search ? Number(search.split("=")[1]) : 1;

  const cart = useSelector(state => state.cart)
  const { cartItems} = cart 
  console.log('cartItems:', cartItems)

  useEffect(() => {
    if(productID) {
      dispatch(addToCart(productID, qty))
    }
  }, [dispatch, productID, qty]) 
    
  return (
    <Row>
      <Col md={8}>
        <h1>Shopping Cart</h1>
        {cartItems.length === 0 ? (
          <Message variant='info'>
            Your cart is empty <Link to='/'>Go Back</Link>
          </Message>
        ) : (
          <ListGroup variant='flush'>
            {cartItems.map(item => (
              <ListGroup.Item key= { item.product }>
                <Row>
                  <Col md={2}>
                    <Image src={item.image} alt={item.name} fluid rounded/>
                  </Col>
                  <Col md={3}>
                    <Link to={`/product/${item.product}`}>{item.name}</Link>
                  </Col>
                  <Col md={2}>
                    ${item.price}
                  </Col>
                </Row>
              </ListGroup.Item>
            ))}
          </ListGroup>
        )}
      </Col>
      <Col md={4}> 
      </Col>
    </Row>
  )
}

错误原因

  1. 直接触发原因:当前列表项使用item.product(产品ID)作为key,如果用户多次添加同一商品到购物车,cartItems数组中会出现多个拥有相同product值的条目,导致React渲染列表时检测到重复key。
  2. 根本原因:addToCart对应的Redux reducer逻辑存在问题——当添加已有商品时,没有累加数量,而是直接向cartItems中新增了一条相同产品ID的记录。

解决方法

方法一:修改Redux Reducer实现商品数量累加(推荐)

修改购物车reducer中处理CART_ADD_ITEM的逻辑,当添加的商品已存在时,仅更新数量而非新增条目:

// 示例reducer代码片段
const cartReducer = (state = { cartItems: [] }, action) => {
  switch (action.type) {
    case 'CART_ADD_ITEM':
      const newItem = action.payload;
      const existingItem = state.cartItems.find(item => item.product === newItem.product);
      
      if (existingItem) {
        // 已有商品则更新数量
        return {
          ...state,
          cartItems: state.cartItems.map(item => 
            item.product === existingItem.product ? { ...item, qty: item.qty + newItem.qty } : item
          )
        }
      } else {
        // 无该商品则新增条目
        return {
          ...state,
          cartItems: [...state.cartItems, newItem]
        }
      }
    // 其他case逻辑...
    default:
      return state;
  }
}

修改后cartItems中同一商品只会存在一条记录,item.product作为key就不会重复。

方法二:使用唯一key(仅在需要保留多条同商品记录时使用)

如果业务需要允许购物车中存在多条同一商品的记录(比如不同规格、属性),需要为每条生成唯一key,比如结合产品ID和唯一标识:

// 假设每条购物车条目有唯一id字段
<ListGroup.Item key={item.id}>
// 临时用index兜底(不推荐,会影响列表更新性能)
<ListGroup.Item key={`${item.product}-${index}`}>

额外小问题修正

代码中ListGroup的属性varient拼写错误,应改为variant,否则组件样式可能无法正常生效。

内容的提问来源于stack exchange,提问作者Erick Cabrera Andrade

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 18:05:44