反应状态表现出奇怪的行为

问题描述 投票:0回答:1

我刚开始反应并为咖啡店制作一个简单的购物车。每当我将一个项目添加到购物车时,如果该项目尚未在购物车中,那么我基本上将其与其余项目一起添加,并将

quantity
属性设置为 1 ,每当我再次添加相同的项目时,我只取整个项目项目并通过执行
quantity++
更新相应的项目数量。但我不知道为什么数量会自行更新两个。我已经尝试过调试它,但我无法理解为什么会发生这种情况,为什么它不更新 1,而是更新 2。

这是我的应用程序组件 -:

import CoffeeShop from "./CoffeeShop"

function App() {

  return (
    <>
      <h1 style={{ textAlign: "center" }}>Coffee Shop</h1>
      <CoffeeShop />
    </>
  )
}

export default App

这是我的 CoffeeShop 组件 -:

在此组件中,我正在处理添加到购物车行为

import "./CoffeeShop.css";
import CoffeeItems from "./CoffeeItems";
import ShoppingCart from "./ShoppingCart";
import { useState } from "react";

export default function CoffeeShop() {

    const [cartItems, setCartItems] = useState([]);
    const [totalPrice, setTotalPrice] = useState(0);

    const addToCart = (id, item) => {
        console.log(cartItems);
        setCartItems(currItems => {
            const idx = currItems.findIndex(cartItem => cartItem.id === id);
            if (idx !== -1) {
                const newItems = [...currItems];
                newItems[idx].quantity++;
                return newItems;
            }
            return [...currItems, { ...item, quantity: 1 }];
        });
        setTotalPrice(currTotalPrice => currTotalPrice + item.price);
    };



    return (
        <div className="CoffeeShop">
            <CoffeeItems addToCart={addToCart} />
            <ShoppingCart cartItems={cartItems} totalPrice={totalPrice} />
        </div>
    );
}

这是我的 CoffeeItems 组件 -:

import { useEffect } from "react";
import { useState } from "react";
import fetchProducts from "./productsApi";
import CoffeeItem from "./CoffeeItem";
import "./CoffeeItems.css";
import { v4 as uid } from "uuid";

export default function CoffeeItems({ addToCart }) {

    const [products, setProducts] = useState([]);
    const [isLoading, setIsLoading] = useState(true);

    useEffect(() => {
        const fetchData = async () => {
            setIsLoading(true);
            const data = await fetchProducts();
            setIsLoading(false);
            for (let product of data) {
                product.id = uid();
            }
            setProducts(data);
        }
        fetchData();

    }, []);


    return (
        <div className="CoffeeItems">

            {isLoading && <h1>Loading...</h1>}
            {products.map(product => <CoffeeItem product={product} addToCart={addToCart} key={product.id} />)}

        </div>
    );
}

**CoffeeItems 组件基本上获取模拟数据,其中每个产品如下:**

{
        "id": 3,
        "name": "Tea set",
        "price": 39.99,
        "description": "This tea set is a complete tea-making solution for tea enthusiasts. It consists of a beautiful and functional kettle for boiling water and a set of delicate tea cups designed for serving tea. The kettle is made of ceramic and comes with a handle and spout for easy pouring. The tea cups are small and dainty with a simple yet elegant design. Whether for a quiet afternoon tea with a friend, a family gathering, or a special event, this tea set offers a classic and sophisticated way to enjoy a relaxing cup of tea.",
        "image": "alisher-sharip-mumpl9-D7Uc-unsplash.jpg"
    }

这是我的 CoffeeItem 组件 -:

import "./CoffeeItem.css";

export default function CoffeeItem({ product, addToCart }) {

    const handleAddToCart = (e) => {
        e.preventDefault();
        addToCart(product.id, product);
    }

    return (
        <div className="CoffeeItem">
            <h2>{product.name}- ${product.price}</h2>
            <img src={product.image} alt="product image" />
            <div>
                <button onClick={handleAddToCart}>Add to cart</button>
            </div>
        </div>
    );
}

这是我的 ShoppingCart 组件 -:

import "./ShoppingCart.css";
import CartItem from "./CartItem";

export default function ShoppingCart({ cartItems, totalPrice }) {

    return (
        <div className="ShoppingCart">
            <h1>Shopping Cart</h1>
            {cartItems.length === 0 && <h2>Your cart is empty</h2>}
            {cartItems.length > 0 && <h2>total: ${totalPrice}</h2>}
            {cartItems.map(cartItem => <CartItem cartItem={cartItem} key={cartItem.id} />)}
        </div>
    );
}

**这是我的 CartItem 组件 -: **

import "./CartItem.css";

export default function CartItem({ cartItem }) {
    return (
        <div className="CartItem">
            <h2>Name: {cartItem.name}</h2>
            <h3>Price: ${cartItem.price}</h3>
            <h3>Quantity: {cartItem.quantity}</h3>
        </div>
    );
}

在 CoffeeShop 组件中,当对购物车中已有的某个商品执行 addCart 处理程序时,它会在代码中添加

+1
。但它实际上将
+2
添加到相应产品的数量属性中。我不知道为什么会发生这种情况。请帮忙。

编辑

我刚刚从 main.jsx 文件中删除,现在一切正常。但为什么?

这是main.jsx文件

import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import App from './App.jsx'
import './index.css'

createRoot(document.getElementById('root')).render(
  <StrictMode>
    <App />
  </StrictMode>,
)

**当我删除一切工作正常。但为什么 ? **

javascript reactjs frontend jsx react-state
1个回答
0
投票

这很微妙,但你正在改变状态:

newItems[idx].quantity++;

在 React 中始终要避免这种情况,并且可能会导致像您所看到的那样的错误。 (具体来说,您看到的也是

StrictMode
渲染组件两次的结果。)

从根本上来说,永远不要改变 React 中的状态。 制作数组的浅拷贝是不够的:

const newItems = [...currItems];

因为两个数组仍然引用相同的对象。 因此,编辑一个数组中的对象会同时在两个数组中编辑该对象。 您可以将数组“投影”到一个新数组中,并在该投影中找到值时替换该值。 例如,考虑这个: setCartItems(currItems => const idx = currItems.findIndex(cartItem => cartItem.id === id); if (idx !== -1) { return currItems.map((item, i) => i === idx ? { ...item, quantity: item.quantity + 1 } : item ); } return [...currItems, { ...item, quantity: 1 }]; });

这里的想法是,当 
map

迭代

currItems
时,它专门寻找您要定位的索引。 对于该索引处的项目,它返回一个全新的项目,其中包含与现有项目相同的属性,但具有新的
quantity
值。 对于数组的每个其他索引,它只按原样返回现有项目。
    

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.