【问题标题】:Changing object in an array does not trigger change in html React更改数组中的对象不会触发 html React 中的更改
【发布时间】:2022-01-08 02:21:29
【问题描述】:

我要编辑的对象以 JSON 格式进行编辑,但只有以前的数据会显示在浏览器中。我使用这些钩子从本地存储中获取产品列表

const Cart = () => {
    const [products, setProducts] = useState([]);
    const [loading, setLoading] = useState(true);

    useEffect(()=>{
        setProducts(loadCart());
        setLoading(false)
    },[])

然后我映射所有对象

   const mapProducts = (products) => {
        return (
            <>
                {products.map((product) => {
                    return (
                        <>
                            <div className="cart-detail">
                                <h4>{product.name} - {product.price}$ 
                                / total: {product.price * product.amount}$</h4>

                                <h4>{product.amount}</h4>
                                <button onClick={() => incrementAmount(product)}>+</button>
                            </div>
                            
                        </>
                    )
                })}
            </>
        )
    }

    return (
        <Base title="Cart">
            {loading && <h1>Loading...</h1>}
            {!loading && mapProducts(products)}
        </Base>
    )

incrementAmount() 函数如下所示:

    const incrementAmount = (product) => {
        let tempList = products
        for (let i = 0; i < tempList.length; i++) {
            if (tempList[i].id === product.id) {
                tempList[i].amount++;
            }
        }
        setProducts(tempList)
    }

从我在控制台中看到的情况来看,数组看起来不错,并且我要编辑的对象已被编辑。 FE:我有一个对象 {name:"hoodie", amount:3} 在单击“+”按钮后它会正确更改为 {name:"hoodie", amount:4}(在 products 和 tempList 中)但是仅在控制台中,在文档中它仍将 product.amount 显示为 3,我不知道为什么

【问题讨论】:

  • 您需要创建一个新的数组实例let tempList = [...products] 并使用它来设置新状态。

标签: javascript reactjs react-hooks use-effect use-state


【解决方案1】:

您可以传递一个函数,而不是将对象传递给setState,当您有一个对象进入您想要保留旧值的状态时,您必须使用一个函数。

因为state 可能会异步更新,所以您不应依赖它们的值来计算下一个状态。

您必须像这样更改incrementAmount() 函数:

const incrementAmount = (product) => {
    setProducts(prevState => {
        const newState = [...prevState];
        for (let i = 0; i < newState.length; i++) {
          if (newState[i].id === product.id) {
            newState[i].amount++;
          }
        }
        return newState;
     });
}

【讨论】:

    【解决方案2】:

    这是因为 react 仅在状态更改时才会触发重新渲染。当您在incrementAmount 中调用setProducts 时,实际上传递的是同一个对象(更新了一个嵌套属性)。所以 react 不会将此注册为状态更改。这是由于对象和数组在 Javascript 中的工作方式。 为了使您的代码正常工作,请将let tempList = products 更改为let tempList = [...products]。这将在内存中创建一个新对象并从products 复制值。最后,当您将其传递给 setProducts 时,将触发重新渲染以更新您的 HTML。

    【讨论】:

      猜你喜欢
      • 2017-09-14
      • 2013-03-21
      • 2017-11-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-08-22
      • 2021-12-06
      • 2020-12-23
      相关资源
      最近更新 更多