状态更新后,React useEffect 不会重新加载我的组件

React useEffect doesn't reload my component after state update

我知道这个问题已经在 Whosebug 上被问过好几次了,但我尝试了几个小时还是无法解决这个问题...

我已经使用 React.js 一年了,但我最近转向了 React hooks 和无状态组件,所以我对它们没有太多经验,如果解决方案很明显,请提前原谅我,因为我在这里问之前真的试着自己解决了...

1.我的代码在做什么:

我有一个简单的 useEffect 钩子,我想在道具 rank 发生变化时调用它。 在挂钩中,我使用 .then 调用 toggleNodeByRank() 方法,并在方法执行后更新名为 data 的状态。

2。发生了什么:

目前,(几乎)一切正常,在第二个 console.log('===StateUpdated===', chartData); 我可以看到我的状态具有正确的更新值。

唯一的问题是我的组件没有重新加载,如果我重复更新 rank 道具的操作,我可以看到修改。

我看到一些回答说deps(rank这里)不好,我也尝试在deps中添加chartData[rank, chartData])但是问题保持不变...

也许有人可以帮我解决这个问题?

useEffect(() => 
  console.log('===PreviousState===', chartData);

  toggleNodeByRank(chartData, rank).then((data) => setChartData(data));

  console.log('===StateUpdated===', chartData);

}, [rank]);

3。编辑

这里是toggleNodeByRank()函数,因为这是我公司的代码所以不想分享太多,希望对大家有帮助..

  const toggleNodeByRank = async (node, rank) => {
    if (node && node.data) {
      // await update node.children depending on node.rank
      // - If I want to toggle the node :
      // I am saving the node.children in a state object (key = node.id, 
      // value = node.children) and I reset the node.children value to [ ]
      // - If I don't want to toggle the node :
      // I don't do anything and juste render
      // update another state to save the node.children data if needed.
      return node;
    }
  };

您在理解 promises 时遇到问题,在您的代码中,此 2 console.log 将输出相同的值,因为 (data) => setChartData(data) 是回调 将在 toggleNodeByRank 完成后调用。 基本上你的代码以这种方式执行:

1) console.log('===PreviousState===', chartData);

2) toggleNodeByRank(chartData, rank); //这里你只是发送请求

3) console.log('===StateUpdated===', chartData);

4) (数据) => setChartData(数据)

所以一切都很好,第二次当你 运行 你看到的组件更新发生了变化 chartData

由于您是在原地改变原始节点元素而不是以不可变的方式更新它,setChartData 不会触发重新渲染,因为反应会检查传递给状态更新程序的值是否实际更改是否来自以前的值,并且由于引用是相同的,它认为没有任何改变

根据 React 原则,您绝不能改变状态值,而是以不可变的方式更新它们。

如果您可以以不可变的方式更新状态,请在 toggleNodeByRank

中进行

但是您仍然可以通过像

这样的浅克隆节点来解决问题
const toggleNodeByRank = async (nodeArg, rank) => {
    const node = {...nodeArg};
    if (node && node.data) {
      return node;
    }
  };

进行上述更改后,它会触发重新渲染,但您必须知道这不是最好的方法