一个简单的React组件为什么会渲染两次?

5

我刚开始创建了一个新的create-react-app项目,并注意到React在渲染组件两次!我的package.json中的React版本是"react": "^16.13.1"

import React, { useRef } from "react";

const App = () => {
  const renders = useRef(0);
  console.log("renders: ", renders.current++);

  return (
    <div>
      Hello
    </div>
  );
};

这将在首次呈现时产生以下效果:
renders: 0
renders: 0

现在如果我添加一个按钮来增加状态,每次状态改变也会产生两个额外的渲染:

import React, { useRef } from "react";

const App = () => {
  const [count, setCount] = useState(0);
  const renders = useRef(0);
  console.log("renders: ", renders.current++);

  return (
    <div>
      <button onClick={() => setCount(count + 1)}>increment</button>
      <div>count: {count}</div>
    </div>
  );
};

这将导致:
//--- initial render
renders: 0
renders: 0
//--- first click
renders: 1
renders: 2
//--- second click
renders: 3
renders: 4
//--- third click
renders: 5
renders: 6

这是正常现象还是最新版本的React中存在的一个bug?


3
这是因为严格模式。所以,在开发中它会运行两次,而在生产中不会。 - Bhojendra Rauniyar
是的,我在做了一些额外的研究后意识到了这一点。谢谢你。 - user3376065
2个回答

13

好的,看起来我找到了原因。在检查index.js之后,我发现了以下内容:

ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById('root')
);

看起来,create-react-app 现在包含了 React.StrictMode。在开发模式下(而不是生产环境下),它会双重调用某些方法。


这是一个功能,可以将一些隐藏的错误显式化:https://github.com/facebook/react/issues/15074#issuecomment-471197572 - Rodrigo Amaral

2

除了你发现的StrictMode问题之外,我认为当你使用ref时,它会创建一个副作用,因此你通常需要将其放在useEffect中以防止它渲染两次:

import React, { useState, useEffect, useRef } from "react";

const App = () => {
  const [count, setCount] = useState(0);
  const renders = useRef(0);
  useEffect(() => {
    // Every time the component has been re-rendered,
    // the counter is incremented
    console.log("renders: ", renders.current++);
  }); 


  return (
    <div>
      <button onClick={() => setCount(count + 1)}>increment</button>
      <div>count: {count}</div>
    </div>
  );
};

export default App;

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