React.js:如何实现将选中商品添加至目标卡片的功能?
修正React添加至购物卡片功能的实现
我帮你梳理下代码里的问题,然后给出修正后的实现,这样你能更清晰理解React状态管理在这个场景下的应用:
import Box from "@mui/material/Box"; import Button from "@mui/material/Button"; import Card from "@mui/material/Card"; import CardContent from "@mui/material/CardContent"; import { styled } from "@mui/material/styles"; import React, { useState, useEffect } from "react"; const StyledBox = styled("div")({ paddingRight: "70px", paddingLeft: "70px", boxShadow: "rgba(100, 100, 111, 0.2) 0px 7px 29px 0px", backgroundColor: "#FFFFFF", border: "1px solid black", minHeight: "200px", paddingTop: "20px", paddingBottom: "20px" }); const AddToCard = () => { // 分开维护商品列表和购物车列表两个独立状态 const [products, setProducts] = useState([]); const [cartItems, setCartItems] = useState([]); // 加载商品数据 useEffect(() => { fetch("https://jsonplaceholder.typicode.com/users") .then((res) => res.json()) .then((result) => setProducts(result)) .catch((e) => console.log(e)); }, []); // 添加到购物车的逻辑:避免重复添加,保证状态更新的不可变性 const addToCardHandleClick = (item) => { const isAlreadyInCart = cartItems.some(cartItem => cartItem.id === item.id); if (!isAlreadyInCart) { setCartItems(prevCart => [...prevCart, item]); } }; return ( <Card sx={{ maxWidth: 700, minHeight: "300px", margin: "20px auto" }}> <CardContent> <Box sx={{ display: "flex", gap: "30px", justifyContent: "center", overflow: "auto" }} > {/* 购物卡片区域:渲染已选中的商品 */} <StyledBox sx={{ minWidth: "200px" }}> <h4>购物卡片</h4> {cartItems.length === 0 ? ( <p>暂无选中商品</p> ) : ( cartItems.map(item => ( <ul key={item.id} style={{ listStyle: "none", paddingLeft: 0 }}> <li>{item.name}</li> </ul> )) )} </StyledBox> {/* 如果需要实现「选中单个商品后点击Move」的逻辑,可在这里加选中状态和Move按钮,我后面会补充示例 */} <Box sx={{ alignSelf: "center", gap: "10px" }} > </Box> {/* 商品列表区域:每个商品配独立的添加按钮 */} <StyledBox> <h4>商品列表</h4> {products.length > 0 ? ( products.map((item) => ( <div key={item.id} style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: "10px" }}> <ul style={{ listStyle: "none", paddingLeft: 0, margin: 0 }}> <li>{item.name}</li> </ul> <Button variant="outlined" onClick={() => addToCardHandleClick(item)} > 添加至购物卡 </Button> </div> )) ) : ( <p>加载中...</p> )} </StyledBox> </Box> </CardContent> </Card> ); }; export default AddToCard;
关键修改点说明:
- 拆分状态:把原来单一的
data拆成products(商品列表)和cartItems(购物车列表),避免两个列表的数据互相干扰,符合React状态管理的单一职责原则。 - 修正添加逻辑:用
some方法检查购物车是否已有该商品,避免重复添加;通过扩展运算符...prevCart更新状态,保证状态的不可变性(React状态更新的最佳实践)。 - 完善渲染内容:左边的购物卡片区域现在会根据
cartItems动态渲染内容,空状态时显示友好提示。 - 优化交互体验:给每个商品单独配置添加按钮,交互逻辑更直观,也更容易理解流程。
如果想要实现你最开始描述的「选中商品后点击统一Move按钮」的逻辑,可以补充以下代码:
// 新增选中商品的状态 const [selectedItem, setSelectedItem] = useState(null); // 修改商品列表的渲染,添加选中样式 products.map((item) => ( <div key={item.id} style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: "10px", border: selectedItem?.id === item.id ? "1px solid blue" : "none", padding: "5px", cursor: "pointer" }} onClick={() => setSelectedItem(item)} > <ul style={{ listStyle: "none", paddingLeft: 0, margin: 0 }}> <li>{item.name}</li> </ul> </div> )) // Move按钮的点击逻辑 const handleMoveClick = () => { if (selectedItem) { const isAlreadyInCart = cartItems.some(cartItem => cartItem.id === selectedItem.id); if (!isAlreadyInCart) { setCartItems(prevCart => [...prevCart, selectedItem]); } setSelectedItem(null); // 清空选中状态 } } // 在中间的Box里渲染Move按钮 <Button variant="outlined" onClick={handleMoveClick} disabled={!selectedItem} > Move </Button>
这样就完全实现了你想要的「选中商品→点击Move按钮→商品进入购物卡片」的完整流程。
内容的提问来源于stack exchange,提问作者user17366197
相关产品推荐
相关产品推荐

