React钩子函数使用相同的原始值调用setState仍会引起重新渲染。

3
我发现当我定义一个值为“1”的状态,并且每次单击按钮时将状态设置为值“2”时,前两次会导致重新渲染。
代码示例:使用 React@17 而不使用严格模式。
演示复制链接:https://codesandbox.io/s/sweet-brattain-ys11d
import { useState } from "react";

export default function App() {
  const [a, setA] = useState("1");
  console.log("render", a);
  return (
    <button
      onClick={() => {
        setA("2");
      }}
    >
      {a}
    </button>
  );
}

// log:
// render 1
// render 2
// render 2

我可以理解第一个重新渲染,因为状态从“1”更改为“2”,

但我不理解第二个重新渲染。


3
对于你的代码,没有2号或增量代码。那么你如何得到render 2?根据上下文理解,此处可能指在某段代码中没有提到数字2或递增代码,但却能够展示出“render 2”的效果。具体实现方法需要结合上下文进行分析。 - prasanth
有什么问题吗?看起来一切都正常。它只渲染一次。为了清楚地检查它,请将a的初始值设置为整数1,而不是字符串,然后在单击按钮时将该值增加1。例如:setA(a + 1) - Robin
另外,假设您的实际代码具有简单的增量功能,而不像您问题中的代码那样,每次状态更改都会获得2个渲染,这可能是由于严格模式引起的:https://mariosfakiolas.com/blog/my-react-components-render-twice-and-drive-me-crazy/ - Jayce444
@prasanth,抱歉我的打字错误,我已经更新了我的代码片段和链接。打开codesandbox链接,多次点击按钮将在控制台中追加两个“render 2”日志。 - Littlee
@Jayce444 我没有在 <React.StrictMode /> 内运行该应用程序。 - Littlee
2个回答

7

我认为这句话很好地解释了这个异常:

如果你将一个State Hook更新为与当前状态相同的值,React会使用Object.is比较算法进行比较,并且不会渲染子元素或触发效果。(译注:React会进行优化并阻止不必要的渲染)

请注意,React在放弃更新之前可能仍需要重新渲染特定的组件。这不应该成为问题,因为React不会“深入”到树中不必要的部分。如果你在渲染时执行了昂贵的计算,可以使用useMemo进行优化。

请注意最后一段话。这是从这里直接引用的。


0

我觉得代码中缺少了一些东西。我在我的端上检查过了,按照我们的期望,它正常工作。

谢谢

import React from "react";
import "./styles.css";
import { useState } from "react";

export default function App() {
  const [a, setA] = useState(1);
  console.log("render", a);
  return (
    <button
      onClick={() => {
        setA(a + 1);
      }}
    >
      {a}
    </button>
  );
}

enter image description here


你好,我已经更新了我的问题。我不是试图增加状态值,而是每次单击按钮时尝试设置相同的值,但是console.log运行的次数比我预期的要多。 - Littlee

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接