【问题标题】:Why setState() isn't working in React in my case?为什么 setState() 在我的情况下不能在 React 中工作?
【发布时间】:2021-12-27 23:55:53
【问题描述】:

我正在尝试通过使用上下文来实现购物车。上下文工作正常,但我需要创建一种每次点击删除一个产品的方法。为此,我必须使用 useState() 函数。但是,它甚至不会改变状态中的数据。

这是我的函数代码。如果有什么不清楚的地方请告诉我

了解更多信息。 productsToPurchase 是一个包含所有已购买产品的数组,如下所示:

[{itemId: "ps-5", qty:2},{itemId: "iphone-xr", qty:4},{itemId:"ps-4", qty:7}]

export const CartContext = createContext()

class CartContextProvider extends Component {

    state = {
        productsToPurchase: [],
        totalPrice:[]
    }

    addProduct = (itemId, prices) => {
        this.setState(oldState => {
            const objWithIdExist = oldState.productsToPurchase.find((o) => o.itemId === itemId);
            return {
                productsToPurchase: !objWithIdExist
                    ? [...oldState.productsToPurchase, { itemId, qty: 1, price: prices }]
                    : oldState.productsToPurchase.map((o) =>
                        o.itemId !== itemId ? o : { ...o, qty: o.qty + 1 }
                    )
            }
        })

        this.setState(oldState=>{
            return{
                totalPrice: getTotalAmount(oldState.productsToPurchase)
            }
        })
    }

    decreaseProduct = (itemId) =>{

        this.setState(oldState=>{

            // catch the item by mapping
            return oldState.productsToPurchase.map(product=>{
                if (product.itemId === itemId){
                    if (product.qty === 1){
                        //remove the product from the list
                        console.log("qty is 1!")
                    }
                    else {
                        console.log("Quantity is more than 1")
                        return  {...product, qty: product.qty - 1}
                    }
                }
            })

        })

    }

    render() {
        return (
            <CartContext.Provider value={{...this.state, addProduct: this.addProduct, decreaseProduct: this.decreaseProduct}}>
                {this.props.children}
            </CartContext.Provider>
        )
    }
}

function getTotalAmount(productsToPurchase) {

    const totalPrice = []

    productsToPurchase.map((product, productIndex) =>{
        product.price.map((price, priceIndex)=>{
            if (productIndex === 0){
                totalPrice.push({currency: price.currency, amount: price.amount * product.qty})
            }
            else {
                totalPrice.map(total=>{
                    if (total.currency === price.currency){
                        total.amount = total.amount + (price.amount * product.qty)
                    }
                })
            }
        })
    })

    return totalPrice
}

export default CartContextProvider;

【问题讨论】:

  • 您需要在setState() 回调中返回新状态。见reactjs.org/docs/hooks-reference.html#functional-updates
  • 您的回调 (oldState =&gt; { ... }) 没有返回任何内容,因此永远不会写入新状态
  • 这是map 回调中的返回,而不是setState 回调。您似乎还使用map 代替for..offorEach,这不是它的用途(为什么开发人员继续这样做?)
  • @asemshaat 您没有返回新状态。应该是return oldState.productsToPurchase.map(...。您传递给setState 的函数需要返回新状态。您正在谈论的返回是嵌套在 inside 的 map 函数。此外,如果您想从列表中删除产品,您也需要使用.filter,或者.reduce 可用于在一次迭代中进行映射和过滤
  • 提供者是一个类组件,而其他一切都是钩子和功能组件,这似乎很奇怪。我会让一切都发挥作用。

标签: javascript reactjs react-context


【解决方案1】:

如果您想从所选产品数量中减去 1,如果达到 0 则将其删除,试试这个

// Make sure you return the new state object in its entirety
this.setState(({ productsToPurchase, ...oldState }) => ({
  ...oldState,
  productsToPurchase: productsToPurchase.reduce((arr, product) => {
    // is this the selected product?
    if (product.itemId === itemId) {
      // product qty > 1, include it with decrement
      if (product.qty > 1) {
        return [...arr, {
          ...product,
          qty: product.qty - 1
        }]
      }
      return arr // otherwise exclude this product
    }
    // otherwise, just include this product
    return [...arr, product]
  }, [])
}))

【讨论】:

  • 这行代码好像太多了。就我而言,我刚刚发现我必须在oldState.productsToPurchase.map(product=&gt;{ 之前添加return。我应该在return{ productsToPurchase: { ...product, qty: product.qty - 1 } } 做些什么
  • 我真的不明白你的意思。仅供参考,没有 cmets 和间距,与原来的 13 行相比,它是 12 行,甚至没有从阵列中删除产品
  • qty = 0 时我还没有删除产品。当qty&gt;0else 部分中时,我正在努力删除产品
  • 第15行。如果从第一行算起
  • @asemshaat 我已改为使用较少行的 reduce。 IMO 它不那么可读,但这是主观的
猜你喜欢
  • 2023-03-26
  • 1970-01-01
  • 2021-03-02
  • 2017-10-03
  • 1970-01-01
  • 2018-08-28
  • 2016-11-06
  • 2013-11-01
  • 1970-01-01
相关资源
最近更新 更多