简体   繁体   English

在 state 更新后 React useEffect 不会重新加载我的组件

[英]React useEffect doesn't reload my component after state update

I know this problem has been asked several times on stackoverflow but i can't make this work even after trying during several hours...我知道这个问题在stackoverflow上已经被问过好几次了,但即使在尝试了几个小时后我也无法完成这项工作......

I am working with React.js for a year now but I recently moved to React hooks and stateless components so I don't have much experience with them so excuse me in advance if the solution is obvious because I really tried to solve it on my own before asking here...我已经使用 React.js 一年了,但我最近转向了 React 钩子和无状态组件,所以我对它们没有太多经验,所以如果解决方案很明显,请提前原谅我,因为我真的试图在我的自己在这里问之前...

1. What my code is doing: 1.我的代码在做什么:

I have a simple useEffect hook that i want to call when the props rank has changed.我有一个简单的useEffect钩子,当道具rank发生变化时我想调用它。 In the hook, i am calling toggleNodeByRank() method using .then and updating my state named data once the method has been executed.在挂钩中,我使用 .then 调用toggleNodeByRank()方法.then并在执行该方法后更新我的 state 命名data

2. What is happenning: 2. 发生了什么:

For now, (almost) everything is working fine and in the second console.log('===StateUpdated===', chartData);目前,(几乎)一切正常,在第二个console.log('===StateUpdated===', chartData); i can see that my state has the correct updated value.我可以看到我的 state 具有正确的更新值。

The only problem is that my component doesn't reload and if I repeat the action that update the rank props, I can see the modifications.唯一的问题是我的组件没有重新加载,如果我重复更新rank道具的操作,我可以看到修改。

I have seen some answers saying that the deps ( rank here) were not good, I have tried to add chartData in the deps aswell ( [rank, chartData] ) but the problem remain the same...我看到一些答案说部门(这里的rank )不好,我也尝试在部门中添加图表数据( [rank, chartData] chartData但问题仍然存在......

Maybe someone can help me on this one?也许有人可以帮我解决这个问题?

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

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

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

}, [rank]);

3. Edit 3. 编辑

Here is the toggleNodeByRank() function, since this is my company's code i prefer not to share too much, I hope this can help you guys..这是toggleNodeByRank() function,因为这是我公司的代码,我不想分享太多,希望对大家有所帮助..

  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;
    }
  };

Since you are mutating the original node element in place instead of updating it in an immutable manner, setChartData isn't triggering a re-render as react checks if the value passed to state updater is actually changed from previous value or not and since the reference is same it believes that nothing has changed由于您正在改变原始节点元素而不是以不可变的方式对其进行更新,因此setChartData不会触发重新渲染,因为反应检查传递给 state 更新程序的值是否实际上从以前的值更改,并且因为参考是一样的 它认为没有任何改变

According to React principles you must never mutate state values instead update them in an immutable way.根据 React 原则,你绝不能改变 state 值,而是以不可变的方式更新它们。

If its possible for you to update the state in an immutable manner, please do that in toggleNodeByRank如果您可以以不可变的方式更新 state,请在 toggleNodeByRank 中进行

However you can still work around by shallow cloning the node like但是,您仍然可以通过浅克隆节点来解决问题,例如

const toggleNodeByRank = async (nodeArg, rank) => {
    const node = {...nodeArg};
    if (node && node.data) {
      return node;
    }
  };

After doing the above change, it would trigger a re-rerender but you must know that it isn't the best way进行上述更改后,它会触发重新渲染,但您必须知道这不是最好的方法

You have problem with understanding promises, in you code this 2 console.log will output same value because (data) => setChartData(data) is callback witch will be called after toggleNodeByRank is done.你在理解承诺方面有问题,在你的代码中,这 2 个 console.log 将 output 相同的值,因为(data) => setChartData(data)是回调,将在 toggleNodeByRank 完成后调用。 Basically your code executes in this way:基本上你的代码以这种方式执行:

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

2) toggleNodeByRank(chartData, rank); 2) toggleNodeByRank(chartData, rank); //here you just send request //这里你只是发送请求

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

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

So everything is fine and second time when u run your component update you see changed chartData所以一切都很好,当您第二次运行组件更新时,您会看到更改chartData

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM