setState 根本不更新状态

时间:2021-01-12 21:25:58

标签: reactjs

我不明白为什么我的 setStock 函数没有更新状态,也没有导致重新渲染,而我还有其他几个函数工作得很好。

const addToStockOperation = async (addOperation) => {
  const payload = {
    ...
  };

  const jwtToken = {
    ...
  };

  const addToStockOperationResult = await axios.put(`${apiEndpoint}/stock/addtoitem`, payload, jwtToken);

    setStock((prevStock) => {
      const indexOfModifiedStock = prevStock.findIndex((stock) => stock._id === addOperation.id);

      console.log(prevStock[indexOfModifiedStock].operations.added.length);
      prevStock[indexOfModifiedStock].operations.added = addToStockOperationResult.data.operations.added;
      console.log(prevStock[indexOfModifiedStock].operations.added.length);
 
      return prevStock;
    });
};

两个控制台日志都确认 prevStock 的修改确实发生了,因为第二个 console.log 显示的长度与前一个长度相比增加了 +1,这表明 prevStock 的所需部分确实已更新,但是,不会导致重新渲染。

我还尝试制作 prevStock const stockCopy = {...prevStock}; 的副本并修改副本并返回副本,但没有任何更改。

我也尝试过简单地 return 1; 只是为了看看是否会触发重新渲染,但仍然没有。

我还有其他一些类似的功能,它们运行良好,并且会按预期进行重新渲染:

这个在设置 products 时工作得很好:

const setProductsWrapper = async (product) => {
  const addProductResult = await axios.post(
    `${apiEndpoint}/product/one`,
    payload,
    token
  );

  addProductResult.data.name === product.name &&
    setProducts((prevProducts) => [addProductResult.data, ...prevProducts]);
};

编辑:我发现了这个问题,愚蠢的我,修改副本后,stock 是一个数组 return [...stockCopy];,有效。

1 个答案:

答案 0 :(得分:2)

返回 prevStock 永远不会起作用,因为它当前状态数组(即与它具有引用相等性)-您需要返回一个新数组以使新渲染成为触发。然而,突变状态似乎也出现了问题。

当您创建副本 const stockCopy = [...prevStock] 时,您正在途中,但问题是这仅将状态数组复制到一个深度级别。任何嵌套在其中的对象,如 .operations,都将保持它们对原始状态数组中对象的引用相等性。

直接改变它们意味着当你返回你的副本时,任何依赖于这些子对象之间引用相等性差异的效果都不会运行,因为它们已经相等了。无需做任何区分。

要解决此问题,您必须深入复制树的相关部分:

setStock((prevStock) => {
    const stockCopy = [...prevStock];
    const stockIndex = stockCopy.findIndex((stock) => stock._id === addOperation.id);
    
    stockCopy[stockIndex] = {
      ...stockCopy[stockIndex],
      operations: {
        ...stockCopy[stockIndex].operations,
        added: addToStockOperationResult.data.operations.added
      }
    };
    
    return stockCopy;
});

State mutation sandbox

当数据结构足够大时,这会变得非常烦人(并且可能很昂贵)。如果可以的话,最好避免在不可变状态下使用这样的结构。当然,通常情况并非如此,如果臃肿的代码开始成为问题,tools to help deal with immutability 可以减少它。