为什么即使旧状态等于新状态,使用相同的值调用 useState 的 setter 也会随后触发组件更新? [英] Why does calling useState's setter with the same value subsequently trigger a component update even if the old state equals the new state?

查看:22
本文介绍了为什么即使旧状态等于新状态,使用相同的值调用 useState 的 setter 也会随后触发组件更新?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

仅当状态值因上次更新而实际更改时才会出现此问题.

在下面的例子中,当第一次点击按钮时,setState"会被点击.用一个新值(12)调用,并且发生组件更新,这是可以理解的.

当我第二次单击同一个按钮时,将状态设置为相同的 12 值会导致组件重新运行(重新渲染),我的主要问题是为什么会发生这种情况.

任何后续设置为 12 的相同值都不会触发组件更新,这也是可以理解的.12 === 12 所以不需要更新.

那么,为什么第二次点击按钮时会发生更新?

导出默认函数 App() {const [state, setState] = useState(0);console.log(组件更新");返回 (

<h1>Hello CodeSandbox {state}</h1><button onClick={() =>setState(12)}>按钮</button>

);}

This problem occurs only if the state value was actually changed due to the previous update.

In the following example, when the button is clicked for the first time, "setState" is called with a new value (of 12), and a component update occurs, which is understandable.

When I click the same button for the second time, setting the state to the same value of 12 it causes the component to re-run (re-render), and why exactly that happens is my main question.

Any subsequent setStates to the same value of 12 will not trigger a component update, which is again, understandable. 12 === 12 so no update is needed.

So, why is the update happening on the second click of the button?

export default function App() {
  const [state, setState] = useState(0);

  console.log("Component updated");

  return (
    <div className="App">
      <h1>Hello CodeSandbox {state}</h1>
      <button onClick={() => setState(12)}>Button</button>
    </div>
  );
}

Codesandbox example

解决方案

The main question is, why logging in function component body causes 3 logs of "Component updated"?

The answer is hiding somewhere in React docs:

if you update a State Hook to the same value as the current state, React will bail out without rendering the children or firing effects.

Nothing new, but then:

Note that React may still need to render that specific component again before bailing out. That shouldn’t be a concern because React won’t unnecessarily go "deeper" into the tree.

But notice useEffect API definition:

will run after the render is committed to the screen.

If you log the change in useEffect you notice only two "B" logs as expected, which is exactly the example for bail out behavior mentioned:

const App = () => {
  const [state, setState] = React.useState(0);

  useEffect(() => {
    console.log("B");
  });

  console.log("A");

  return (
    <>
      <h1>{state}</h1>
      <button onClick={() => setState(42)}>Click</button>
    </>
  );
};

There will be an additional "Bail out" call for App component (extra "A" log), but React won't go "deeper" and won't change the existing JSX or state (no additional "B" will be logged).

这篇关于为什么即使旧状态等于新状态,使用相同的值调用 useState 的 setter 也会随后触发组件更新?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆