React点击删除按钮后购物车组件重复渲染问题求助
React购物车删除商品后重复渲染问题
我是React新手,正在制作电商网站用于练习。购物车组件从API动态渲染购物车商品,已100%确认问题出在前端。初始渲染时一切正常,数据库中的购物车内容均可正常显示,但点击购物车商品上的“Remove From Cart”按钮后,每个购物车商品都会重复显示。
相关组件代码
CartCard.jsx
(/api/delete 返回删除后的购物车JSON对象,删除逻辑由API处理)
import React from "react"; import CartCardCSS from "./CartCard.module.css"; export default function CartCard(props) { const passCart = props.passCart; function deleteFromCart(e) { e.preventDefault(); const item = { id: props.id, mainText: props.mainText, price: props.price, type: props.type } const user = { username: props.username } const compoundEntity = { theContent: item, theUser: user } const requestOptions = { method: "POST", headers: {"Content-Type" : "application/json"}, body: JSON.stringify(compoundEntity) } fetch("/api/delete", requestOptions) .then(response => response.json()) .then(response => { passCart(response) console.log(response) }) } return ( <div className={CartCardCSS.card}> <img src={props.image} className={CartCardCSS.itempicture} alt="item picture"/> <h3 className={CartCardCSS.subitem}>{props.mainText}</h3> <h4 className={CartCardCSS.subitem}>{props.price}</h4> <button onClick={deleteFromCart} className={`${CartCardCSS.subitem} ${CartCardCSS.button}`} type="button">Remove From Cart</button> </div> ) }
Cart.jsx
import React, {useEffect, useState} from "react"; import CartCard from "./CartCard"; import CpuPicture from "./img/cpu.jpg"; import GpuPicture from "./img/gpu.jpg"; export default function Cart(props) { const cart = props.cart; const username = props.username; const passCart = props.passCart; const [arrCart, setArrCart] = useState(Object.values(cart)) const [cartComp, setCartComp] = useState() useEffect(() => { console.log(cart) setArrCart(Object.values(cart)) for(let i = 0; i < arrCart.length; i++) { setCartComp(arr => [arr, <CartCard key={i} id={i} passCart={passCart} username={username} mainText={arrCart[i].mainText} price={arrCart[i].price} type={arrCart[i].type} image={arrCart[i].type === "cpu" ? CpuPicture : GpuPicture}/>]) } }, [cart]) return ( <div> <h2 >Cart:</h2> {cartComp} </div> ) }
Profile.jsx
import React from "react"; import Cart from "./Cart"; import Navbar from "./Navbar"; import {useNavigate} from "react-router-dom"; export default function Profile(props) { const username = props.username; const isLoggedIn = props.isLoggedIn; const cart = props.cart; const passCart = props.passCart; let navigate = useNavigate(); const routeChange = () => { let path = "/login"; navigate(path); } if (isLoggedIn) { return ( <div> <Navbar /> <h1>{username}</h1> <Cart passCart={passCart} username={username} cart={cart} /> </div> ) } else { routeChange(); } }
App.jsx
import React, {useState} from "react"; import './App.css'; import Login from "./components/Login"; import Signup from "./components/Signup"; import Home from "./components/Home"; import Profile from "./components/Profile"; import Card from "./components/Card"; import GpuPicture from "./components/img/gpu.jpg"; import CpuPicture from "./components/img/cpu.jpg"; import {BrowserRouter, Routes, Route, Navigate} from "react-router-dom"; function App() { const [username, setUsername] = useState(''); const [cart, setCart] = useState(''); const [isLoggedIn, setIsLoggedIn] = useState(false) function passUsername(items) { setUsername(items); } function passCart(items) { setCart(items); } function passIsLoggedIn(items) { setIsLoggedIn(items); } return ( <div className="App"> <BrowserRouter> <Routes> <Route path="/" element={<Navigate to="/login"/>} /> <Route path="/login" element={<Login passIsLoggedIn={passIsLoggedIn} passUsername={passUsername} passCart={passCart}/>}/> <Route path="/signup" element={<Signup />}/> <Route path="/home" element={<Home passCart={passCart} cart={cart} username={username} isLoggedIn={isLoggedIn} />} /> <Route path="/profile" element={<Profile passCart={passCart} cart={cart} username={username} isLoggedIn={isLoggedIn}/>} /> </Routes> </BrowserRouter> </div> ); } export default App;
问题根源及修复方案
核心问题
Cart.jsx中存在两个关键错误:
- 状态更新逻辑错误:在
useEffect里循环调用setCartComp时,每次都是将新组件追加到旧数组中,且arrCart的更新是异步的,导致每次删除操作后都会累加渲染旧的组件,造成重复显示。 - key值使用不当:用循环索引
i作为组件的key,React无法正确识别组件的增减,会导致渲染异常。
修复后的Cart.jsx
import React, { useEffect, useState } from "react"; import CartCard from "./CartCard"; import CpuPicture from "./img/cpu.jpg"; import GpuPicture from "./img/gpu.jpg"; export default function Cart(props) { const { cart, username, passCart } = props; const [arrCart, setArrCart] = useState(Object.values(cart)); // 监听cart变化,同步更新arrCart useEffect(() => { setArrCart(Object.values(cart)); }, [cart]); // 直接在渲染阶段生成购物车组件列表,无需维护cartComp状态 const cartItems = arrCart.map((item) => ( <CartCard key={item.id} // 使用商品自身的唯一id作为key,不要用索引 id={item.id} // 传递商品真实id,确保删除逻辑正确 passCart={passCart} username={username} mainText={item.mainText} price={item.price} type={item.type} image={item.type === "cpu" ? CpuPicture : GpuPicture} /> )); return ( <div> <h2>Cart:</h2> {cartItems} </div> ); }
额外优化
App.jsx中cart的初始状态应设为空对象,避免初始时Object.values(cart)处理空字符串出错:
const [cart, setCart] = useState({});
内容的提问来源于stack exchange,提问作者Elliott Phillips
相关产品推荐
相关产品推荐

