React useReducer购物车:添加多商品项后删除功能异常求助
问题原因分析
你的问题根源有两个:
- 用index作为React元素的key:当列表项被删除后,剩余项的index会重新排序,React会基于index复用组件,导致内部状态和实际数据不匹配。
- 删除逻辑的参数错误:删除时你传递的是
index,但在reducer里是用item.id来过滤的,当列表项的index变化后,传递的index和item的id不再对应。
举个具体场景:
- 添加两个商品,第一个id=0(index=0),第二个id=1(index=1)。
- 删除第一个商品后,第二个商品的index变成0,但它的id还是1。
- 点击删除这个商品时,传递的index是0,reducer里执行
state.filter(x => x.id !== 0),而这个商品的id是1,所以不会被过滤掉,导致删除失败。
修复方案
1. 生成唯一且稳定的item id
不要用state.length生成id(删除后再添加会出现重复id),可以用一个自增的计数器:
import { useReducer, useRef } from "react"; export default function App() { const inputRef = useRef(); const idCounter = useRef(0); // 用ref存自增id const [items, dispatch] = useReducer((state, action) => { switch (action.type) { case "add": return [ ...state, { id: idCounter.current++, // 每次添加自增 name: action.name } ]; case "remove": return state.filter((x) => x.id !== action.id); // 用id过滤 default: return state; } }, []); function handleSubmit(e) { e.preventDefault(); if (inputRef.current.value !== "") { dispatch({ type: "add", name: inputRef.current.value }); } inputRef.current.value = ""; } return ( <div className="App"> <form onSubmit={handleSubmit}> <input ref={inputRef} /> </form> <ul> {items.map((item) => ( <li key={item.id}> {/* 用item.id作为key */} {item.name} <button onClick={() => dispatch({ type: "remove", id: item.id })}> X </button> </li> ))} </ul> </div> ); }
2. 核心修改点
- 用
useRef维护一个自增的idCounter,确保每个item的id唯一且不会随列表变化而改变。 - 列表项的
key改用item.id,保证React能正确识别每个元素,不会因为列表变化复用错误的组件。 - 删除时传递
item.id而非index,reducer里通过id过滤数据,逻辑准确。
内容的提问来源于stack exchange,提问作者Sougata Mukherjee
相关产品推荐
相关产品推荐

