【问题标题】:React hooks useState setValue still rerender one more time when value is equal当 value 相等时,React hooks useState setValue 仍然重新渲染一次
【发布时间】:2019-08-26 05:24:31
【问题描述】:

我有下面的示例代码:

function App() {
  console.log("render");
  const [val, setVal] = React.useState(0);
  return (
    <div className="App">
      <h1>{val}</h1>
      <button onClick={() => setVal(12)}>Update with same value</button>
    </div>
  );
}

当我多次单击一个按钮时,控制台会记录 3 次“渲染”消息。对我来说,应该只有 2 次:

  • 1 用于第一次渲染

  • 2 用于从 val 0 更新到 12(单击按钮时)

从那时起,它不应重新渲染,因为相同的值 (12) 已更新为 val。

但为什么它出现了 3 次?这意味着尽管更新了相同的值,它仍会再重新渲染一次。

哪位知道的请解释一下,先谢谢了。

P/S:我发现它只会在值更改然后用相同值更新时导致额外的重新渲染

function App() {
  console.log("render");
  const [val, setVal] = useState(4);
  return (
    <div className="App">
      <h1>{val}</h1>
      <button onClick={() => {
        setVal(val => val + 1)
      }}>Update</button>
      <button onClick={() => {
        setVal(val => val)
      }}>Update with same value</button>
    </div>
  );
}

当第一次点击第二个按钮时,没有重新渲染调用,但是如果你点击第一个按钮然后点击第二个按钮,第二个按钮会导致 1 次额外的重新渲染

【问题讨论】:

    标签: javascript reactjs frontend react-hooks


    【解决方案1】:

    这个帖子可以帮助你:React: Re-Rendering on Setting State - Hooks vs. this.setState

    另外,您可以查看here 上的第二段:

    请注意,React 在退出之前可能仍需要再次渲染该特定组件。这不应该是一个问题,因为 React 不会不必要地“深入”到树中。如果您在渲染时进行昂贵的计算,您可以使用 useMemo 对其进行优化。

    【讨论】:

      【解决方案2】:

      React 无法猜测 render() 的输出不会改变:它必须再次 render() 并将结果与​​之前的 render() 进行比较。

      然后神奇的事情发生了:如果没有差异,则 DOM 不会更新;如果存在差异,它会尝试仅根据需要创建/销毁元素,因为那是昂贵的部分,而不是运行 render() - 不应该。

      更改状态通常会触发对 render() 的调用(不一定是 DOM 修改)——但如果您想控制该行为,请定义 shouldComponentUpdate


      注意:这适用于非钩子组件。但是,我不知道 hooks 的行为与常规组件的行为略有不同:看来您期望 setState 在值不变时不触发渲染是正确的— 见 Yash Joshi 的回答。

      【讨论】:

      • 我们也可以在类组件中使用PureComponent,而不是手动定义shouldComponentUpdate。但当数据嵌套较深时,更喜欢shouldComponentUpdate
      • 是的,但是我还是不知道为什么react需要在值不变的情况下再调用一次render。
      • 在非钩子的情况下,预期:React 选择比较旧/新的 render() 输出而不是旧/新状态。在您的情况下(钩子),文档说如果值不变,则保证仅跳过子项的呈现。至于为什么它可能仍然需要重新渲染钩子,我没有解释......
      • 如果您想知道额外重新渲染背后的原因,请查看此评论链接:github.com/facebook/react/issues/14810#issuecomment-462089702
      • 我已经阅读了该评论并发现当值更改然后再次使用相同的值更新时,它只会导致 1 次额外的重新渲染(我编辑了我的帖子)。但老实说,仍然不知道为什么需要再调用 render 1 次 :(
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-08-15
      • 1970-01-01
      • 2021-09-19
      • 2021-09-09
      • 2019-06-26
      • 2021-07-15
      相关资源
      最近更新 更多