反应状态不从临时变量设置对象

React state not setting Object from temporary variable

抱歉,我知道这是一个常见问题,但我找不到正确的答案。我正在使用一个功能组件,它从 API 中获取 JSON 个对象的列表。列表数据没有我需要的所有信息,因此我遍历提供的 ID 列表并获取每个 'show' JSON 确实有我需要的信息。然后我将它们放入状态数组中。这很混乱,但它运作良好。当我迭代和获取个人 'show' JSON 时,我想对某些值进行一些数学运算。我将该信息放入一个对象中,但是当我尝试将该对象设置为 state 它只是不起作用,即使我可以记录该对象并且它按预期显示。

  const getStashList = async () => {
        <Code to fetch list data>
    }

    useEffect(() => {
        getStashList()
    }, [])

const getFullStashData = (data) => {
        const tempWeightObj = {}
        let fullStashArray = []
        try {
            data.forEach(async (stashItem) => {
                const indStashResponse = await fetch(`<the api address>`, {
                    method: 'GET',
                    headers: {
                        Authorization: "Bearer " + access_token
                    },
                    mode: 'cors'
                })
                const indStashData = await indStashResponse.json()
                fullStashArray.push(indStashData.stash)

                const amountStashed = indStashData.total_yards

                let weightName = indStashData.weight_name
                Object.defineProperty(tempWeightObj, weightName, {
                    value: amountStashed,
                    writable: true
                })
                console.log(tempWeightObj) //This logs the expected object
            })
        } catch (err) {
            console.error(`Error in fetch: ${err.message}`)
        }
        setFullStash(fullStashArray) //This state is set as expected
        setWeightYards(tempWeightObj) //The state is still empty

    }

    useEffect(() => {
        getFullStashData(stashList)
    }, [stashList])

getFullStashData函数体是完全同步的。它声明 tempWeightObjfullStashArray,同步运行 forEach,并将状态更新入队。 async forEach 循环回调然后改变函数范围内关闭的引用。

你看到的是突变。

我建议重构,将 getFullStashData 函数声明为 async,将 data 参数映射到 fetch Promise 对象数组,等待数组响应映射到另一个 Promise 对象数组,这次返回 JSON 数据。您现在有 fullStashArray 数组来更新状态。迭代此 fullStashArray 数组以填充 tempWeightObj 对象的属性。全部完成后然后将状态更新加入队列。

const getFullStashData = async (data) => {
  try {
    const reqs = data.map((stashItem) =>
      fetch(`<the api address>`, {
        method: "GET",
        headers: {
          Authorization: "Bearer " + access_token
        },
        mode: "cors"
      })
    );
    const responses = await Promise.all(reqs);
    const fullStashArray = await Promise.all(responses.map((res) => res.json()));

    const tempWeightObj = {};
    fullStashArray.forEach(
      ({ total_yards: value, weight_name: weightName }) => {
        Object.defineProperty(
          tempWeightObj,
          weightName,
          { value, writable: true }
        );
      }
    );

    setFullStash(fullStashArray);
    setWeightYards(tempWeightObj);
  } catch (err) {
    console.error(`Error in fetch: ${err.message}`);
  }
};