javascript - 为什么 React 在设置状态为相同值后会第二次渲染组件?

标签 javascript reactjs

我有一个简单的 React 组件,每次单击按钮时我都设置相同的值:

import React, { useState } from 'react';
import './style.css';

let data = { title: 'ABC' };

export default function App() {
  const [foo, setFoo] = useState();

  console.log('Rendered');

  return (
    <div>
      <button onClick={() => setFoo(data)}>Set Data</button>
      <h1>Data: {JSON.stringify(foo)}</h1>
    </div>
  );
}

但是渲染有点奇怪,因为在第二个按钮上单击 React 渲染组件但我设置了相同的值。 为什么 React 重新渲染组件,尽管我设置了相同的值?

Demo Image

Demo Here

最佳答案

问题是为什么组件在新状态等于之前状态的情况下渲染(浅比较)

// On second button click
const prevState = data

// State trigger
setFoo(data)

// Same state, it doesn't triggers a render
data === prevState

因此,由于状态改变,组件没有触发渲染。

它是由于另一个原因而发生的,正如 Hooks API Bailing out of a state update section 下“字里行间”的文档中提到的那样:

Note that React may still need to render that specific component again before bailing out.

与类组件不同,对于函数组件,在设置相同状态之后,有时,React 将需要另一个渲染来验证其相等性。 这是不幸的边缘案例

但它不应该将您视为“性能问题”,因为它不会影响 React.Node 树,它不会在 reconciliation 中继续。如果状态没有改变,则进行处理。它甚至不会进行不必要的 Hook 调用。

另一个简化的例子

这里也是一样,还有另一个用于保释的渲染,另一个“A”日志。

虽然有一个“救助”渲染,但请注意 useEffect 没有运行。

import React, { useEffect } from "react";
import ReactDOM from "react-dom";

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>
    </>
  );
};

ReactDOM.render(<App />, document.getElementById("root"));

Edit  React state trigger

如果您想了解日志顺序(“为什么‘A’先于‘B’登录?”),请尝试深入研究另一个问题:React useEffect in depth / use of useEffect?

关于javascript - 为什么 React 在设置状态为相同值后会第二次渲染组件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68829328/

相关文章:

javascript - 在 react 中添加元素的正确方法?

javascript - Angular force 在 url 中出现不需要的感叹号

javascript - 如何将输入值从一个表单传递到同一jsp页面的另一个表单?

javascript - 有没有办法通过网络检查机器上安装了哪些字体?

javascript - JQuery 只加载页面的最后 n 行

javascript - 创建 React 函数组件时,使用粗箭头函数还是常规 ES5 函数更好?

reactjs - Next.js-before-hydration、Next.js-hydration 和 FCP

javascript - 将项目动态添加到现有列表

javascript - Bootstrap Form.Control 选择填充了格式为 'MONTH YYYY' 的日期字符串选项

reactjs - 如何在 React Native 中将 ref 从父级传递给子级 Touchable Opacity?