【问题标题】:Why does setState Hook from React is rendering twice even not changing the state?为什么 React 的 setState Hook 会渲染两次,甚至不改变状态?
【发布时间】:2021-11-07 09:11:26
【问题描述】:

我正在研究 React 挂钩并在代码中插入一些控制台日志以更好地理解渲染流程。然后我开始模拟发送相同值的 setState 效果,看看 React 是否会再次渲染它。

import { useState } from "react";

function ManComponent() {
  /* States */
  const [shirt, setShirt] = useState("Blue Shirt");
  console.log("Rendering man with "+shirt);
  
  /* Actions */
  const changeShirt = (newShirt) => {
    console.log("[Man] Changing shirt from "+shirt+" to "+newShirt);
    setShirt(newShirt);
  };
  
  
  return (
    <div>
      <p>The man is using: {shirt}</p>
      
      <div>
        <button onClick={() => changeShirt("Red Shirt")}>Change to red shirt</button>
        <button onClick={() => changeShirt("Blue Shirt")}>Change to blue shirt</button>
      </div>
    </div>
  );
}

export default function App() {
  console.log("Rendering app");

  return (
    <ManComponent />
  );
}

如果我单击“更改为红色衬衫”三次,我会收到两条日志,说明组件正在渲染。它应该只有一个,因为我只更改了一次值,对吧?

我的问题是理解为什么如果状态只改变一次,组件会渲染两次。

P.S:我尝试删除严格模式,但没有效果。顺便说一句,我使用的是 React 17 版本。

【问题讨论】:

  • 你应该使用一个 useEffect hook 将衬衫状态作为依赖项,这样它只会记录一次,因为它会忽略除对该状态所做的更改之外的所有其他更改。

标签: javascript reactjs console use-state


【解决方案1】:

发生了什么

React 文档在 useState hook API 中准确解决了这种行为。

退出状态更新

如果您将 State Hook 更新为与当前状态相同的值,React 将退出而不渲染子级或触发效果。 (React 使用 Object.is comparison algorithm。)

请注意,React 可能仍需要在退出之前再次渲染该特定组件。这不应该是一个问题,因为 React 不会不必要地“深入”到树中。


这不是严格模式

Strict mode 是一个很好的猜测,因为它曾经在 React 17 之前的渲染周期中触发重复日志,尽管它已更新为使这些重复日志静音以避免confusion

从 React 17 开始,React 会自动修改 console.log() 等控制台方法,以在第二次调用生命周期函数时使日志静音。但是,在 a workaround can be used.

的某些情况下,它可能会导致不良行为

...caused additional confusion,导致 another update 的严格模式日志记录行为(我相信尚未发布)。

上面引用中提到的使用日志调试严格模式渲染的解决方法是保留日志函数的模块范围副本。

const log = console.log;

const App = () => {
  log('Will not be silenced by React');
  return //...
};

【讨论】:

  • 我一直在阅读所有关于它的资料。我相信这种行为与日志记录问题无关。 useState 挂钩在与实际状态进行比较之前调用组件的另一次渲染。而且,它不会在下一次尝试中发生。只是我试图理解 DOM 更新的 React 算法。
  • @NícolasAmarante 您遇到的行为是我回答的第一部分,React 退出但仍重新呈现当前组件。其余的答案是澄清为什么它不是严格模式日志记录问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-03-17
  • 1970-01-01
  • 2023-01-24
  • 2020-07-05
  • 1970-01-01
  • 2015-08-27
相关资源
最近更新 更多