避免在所有状态更改时发生反应组件重新渲染

问题描述 投票:0回答:1

我的

<App />
组件有 2 个状态。第一个状态在用户交互时更新,然后使用
useEffect()
钩子触发第二个状态的更新。这会在用户单击按钮时导致 2 次重新渲染。有人可以帮我弄清楚如何在第二次状态更新后重新渲染
<App />
吗?这是一个糟糕的反应模式吗?

这里是codesandbox:https://codesandbox.io/s/wispy-butterfly-nm5fsr

您可以查看控制台以查看重新渲染。

我需要解决这个问题的原因是因为我有一个真实的项目,其中正在发生重新渲染并且在组件之间传递非常大的道具。重新渲染导致明显的延迟。我会分享整个项目,但这对于堆栈溢出问题来说太多了。

reactjs design-patterns react-hooks gatsby
1个回答
0
投票

它渲染两次,因为每次渲染更新一次状态,而不是同时更新两个状态。考虑一下你在这里做什么:

const handleClick = () => {
  if (state1) setState1((prev) => prev + 1);
  else setState1(1);
};

useEffect(() => {
  if (state1) setState2(state1 + 10);
}, [state1]);

这基本上意味着:

更新

state1
并重新渲染。在下一次渲染时,更新
state2
并重新渲染。

获取状态更新的计算并不是非常复杂。将

1
添加到数字,并将
10
添加到数字。您无需等待组件重新渲染即可知道
state1
是什么。它将是当前值加1,这很容易计算。您可以使用该计算来更新这两个状态:

const handleClick = () => {
  if (state1) {
    const newState1 = state1 + 1;
    setState1(newState1);
    setState2(newState1 + 10);
  } else {
    setState1(1);
    setState2(10);
  }
};

或者,更好,您一开始就不需要两个状态值。在这个例子中,

state2
派生自
state1
(这样做并不是一个困难或昂贵的计算)。这意味着您正在重复状态。

不要重复状态。只需从

state1
导出第二个值:

const [state1, setState1] = useState(null);

const handleClick = () => {
  if (state1) setState1((prev) => prev + 1);
  else setState1(1);
};

return (
  <div className="App">
    {console.log("Rerendering children...")}
    <Child1 state1={state1} />
    <Child2 state2={state1 ? state1 + 10 : null} />

    <button type="button" onClick={handleClick}>
      Change State 1!
    </button>
  </div>
);
© www.soinside.com 2019 - 2024. All rights reserved.