为啥 setState() 在我的情况下不能在 React 中工作?

Posted

技术标签:

【中文标题】为啥 setState() 在我的情况下不能在 React 中工作?【英文标题】: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 可用于在一次迭代中进行映射和过滤 提供者是一个类组件,而其他一切都是钩子和功能组件,这似乎很奇怪。我会让一切都发挥作用。 【参考方案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 它不那么可读,但这是主观的

以上是关于为啥 setState() 在我的情况下不能在 React 中工作?的主要内容,如果未能解决你的问题,请参考以下文章

如何在我的 setState 函数调用中使用变量?

为啥转换在我的情况下不起作用

为啥在我的情况下快速排序总是比冒泡排序慢?

为啥 ByteBuffer putShort(value) 的方法在我的情况下无法正常工作?

为啥setState是异步的

为啥有 2 个 setState 可用 [重复]