reactjs ++将值递增2而不是1

qni6mghb  于 2023-05-28  发布在  React
关注(0)|答案(4)|浏览(91)

我正在使用下面的reducer添加产品,删除它们,并将它们添加到购物车。我希望'ADD_TO_CART'操作在调度时将一个项目添加到购物车,但如果一个项目已经在购物车中,我希望将其增加1。但是,该方法将购物车项增加2而不是1

export default (state, action) => {
  switch (action.type) {
    case 'ADD_PRODUCT':
      return {
        ...state,
        products: [action.payload, ...state.products]
      }

    case 'DELETE_PRODUCT':
      return {
        ...state,
        products: state.products.filter(product => product.id !== action.payload)
      }

    case 'ADD_TO_CART':
      if (state.cart.some(cartItem => cartItem.id === action.payload.id)) {
        const updatedItemIndex = state.cart.findIndex(cartItem => cartItem.id === action.payload.id)
        let cartItems = [...state.cart]
        let itemToUpdate = cartItems[updatedItemIndex]
        itemToUpdate.quantity++
        return { ...state, cart: cartItems }
      } else {
        const newItem = { ...action.payload, quantity: 1 }
        return { ...state, cart: [...state.cart, newItem] }
      }

    default:
      return state
  }
}

这是调度操作的代码

function addToCart(product) {
  dispatch({
    type: 'ADD_TO_CART',
    payload: product
  })
}

我正在调用以下组件中的操作

import React, { useContext } from 'react'
import { ProductContext } from './ProductContext'

export const ProductCard = ({ product }) => {
  const { deleteProduct, addToCart } = useContext(ProductContext)

  const handleDelete = () => {
    deleteProduct(product.id)
  }

  const handleCart = () => {
    addToCart(product)
  }

  return (
    <div className='product__card'>
      <h3>{product.productName}</h3>
      <p>{product.price}</p>
      <button className='button'>View Product</button>
      <button onClick={handleCart} className='button'>Add to Cart</button>
      <button onClick={handleDelete} className='button'>Delete</button>
    </div>
  )
}
mwkjh3gx

mwkjh3gx1#

尝试将数量从数字更改为空报价。

Old: const newItem = { ...action.payload, quantity: 1 }

New: const newItem = { ...action.payload, quantity: '' }
snvhrwxg

snvhrwxg2#

你搞错了你改变了你的状态。

let cartItems = [...state.cart] // <-- reinitialize only the array,
        // the array items remains with the same reference!!!!
        let itemToUpdate = cartItems[updatedItemIndex]
        itemToUpdate.quantity++ // <--- this will mutates your state!!!
        return { ...state, cart: cartItems }

修复:创建一个新项目,并复制数据与传播运算符,并删除旧的。

lrl1mhuk

lrl1mhuk3#

我遇到了同样的问题,情况非常相似,目前的答案都没有帮助我。因此我只能推荐

itemToUpdate.quantity++

被改成

itemToUpdate.quantity += 0.5;

我知道这不是解决这个问题的正确方法,但功能工作,你可以改变它以后当你会找到解决方案

kpbpu008

kpbpu0084#

问题

这里的问题是状态突变。cart数组是浅复制的,但itemToUpdate * 仍然 * 是对前一状态的对象的引用,itemToUpdate.quantity++改变了这个对象引用。

case "ADD_TO_CART":
  if (state.cart.some((cartItem) => cartItem.id === action.payload.id)) {
    const updatedItemIndex = state.cart.findIndex(
      (cartItem) => cartItem.id === action.payload.id
    );
    let cartItems = [...state.cart];
    let itemToUpdate = cartItems[updatedItemIndex];
    itemToUpdate.quantity++;                        // <-- mutation!
    return { ...state, cart: cartItems };
  } else {
    const newItem = { ...action.payload, quantity: 1 };
    return { ...state, cart: [...state.cart, newItem] };
  }

reducer函数可能被调用两次,作为React.StrictMode组件检测意外副作用的一部分。
以下是文档的一个片段,重点是我的:
严格模式不能自动为您检测副作用,但它可以通过使它们更具确定性来帮助您发现它们。这是通过***故意双重调用***以下函数实现的:

  • 类组件constructorrendershouldComponentUpdate方法
  • 类组件静态getDerivedStateFromProps方法
  • 功能组件体
  • 状态更新函数(setState的第一个参数)
  • 传递给useStateuseMemo或***useReducer***的函数

有关当前文档中的相同/类似信息,请参阅在开发中修复通过双重渲染发现的错误。

解决方案

更新状态时,浅复制所有正在更新的状态**和嵌套状态***。除了浅复制cart数组之外,还应该将正在更新的购物车项目浅复制到一个新的对象引用中, 然后 * 覆盖正在更新的属性。
示例:

case "ADD_TO_CART":
  if (state.cart.some((cartItem) => cartItem.id === action.payload.id)) {
    return {
      ...state,
      cart: state.cart.map((item) =>      // <-- shallow copy cart array
        item.id === action.payload.id
          ? {                             // <-- new cart item object reference
              ...item,                    // <-- shallow copy cart item
              quantity: item.quantity + 1 // <-- update property
            }
          : item
      )
    };
  } else {
    const newItem = { ...action.payload, quantity: 1 };
    return { ...state, cart: [...state.cart, newItem] };
  }
    default:
      return state;
  }
};

我知道Redux并没有在这篇文章的代码中使用,但是他们有一个很棒的文档,关于Immutable Update Patterns的原因和应用,你应该看看。

相关问题