React Hooks 渲染两次

Ste*_*ley 17 javascript rerender reactjs react-hooks

我定义了一个场景:我们有一个使用父级道具和自身状态的组件。

有两个组件 DC 和 JOKER 以及我在下面的步骤:

  1. 单击 DC 的按钮
  2. DC 设置计数
  3. JOKER 将使用旧状态进行渲染
  4. 运行 useEffect 和 setCount
  5. JOKER 再次渲染

在此处输入图片说明

我想问一下为什么 JOKER 渲染两次(第 3 步和第 5 步),而第一个渲染浪费了性能。我只是不想要第 3 步如果在类组件中,我可以使用 componentShouldUpdate 来避免它。但是 Hooks 有同样的东西吗?

我的代码在下面,或者打开这个网站https://jsfiddle.net/stephenkingsley/sw5qnjg7/

import React, { PureComponent, useState, useEffect, } from 'react';

function JOKER(props) {
  const [count, setCount] = useState(props.count);
  useEffect(() => {
    console.log('I am JOKER\'s useEffect--->', props.count);
    setCount(props.count);
  }, [props.count]);

  console.log('I am JOKER\'s  render-->', count);
  return (
    <div>
      <p style={{ color: 'red' }}>JOKER: You clicked {count} times</p>
    </div>
  );
}

function DC() {
  const [count, setCount] = useState(0);
  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => {
        console.log('\n');
        setCount(count + 1);
      }}>
        Click me
      </button>
      <JOKER count={count} />
    </div>
  );
}

ReactDOM.render(<DC />, document.querySelector("#app"))
Run Code Online (Sandbox Code Playgroud)

小智 41

这是 StrictMode 的一个有意特性。这只发生在开发阶段,有助于发现渲染阶段的意外副作用。我们只对带有 Hook 的组件执行此操作,因为它们更有可能在错误的地方意外产生副作用。-- gaearon 于 2019 年 3 月 9 日发表评论

  • 我在这里失去了理智,答案是“这是一个功能,而不是一个错误”。不管怎样,+1,谢谢! (6认同)

Jun*_*aza 15

您只需在./index.js中进行修改即可

改变这个

 <React.StrictMode>
    <App />
 </React.StrictMode>
Run Code Online (Sandbox Code Playgroud)

对此

 <>
    <App />
  </>
Run Code Online (Sandbox Code Playgroud)

React.StrictMode 导致组件在开发模式下渲染。(适用于reactjs版本18.0.2)

  • 首先,StrictMode 是一个用于突出显示应用程序中潜在问题的工具。与 Fragment 一样,StrictMode 不会渲染任何可见的 UI。它为其后代激活额外的检查和警告,严格模式检查仅在开发模式下运行,它们不会影响生产。当严格模式处于活动状态时,所有组件都会在再次重新安装之前安装和卸载。这就是它渲染两次的原因。希望有帮助! (2认同)

Den*_*nis 2

我不确定我是否理解你的问题,但就这样吧。

当您的<DC />组件更改状态时,它将新的状态值传递count给组件 Joker。此时,组件将重新呈现,并考虑第一个更改。

然后将效果绑定到props.count更改;

  useEffect(() => {
    console.log('I am JOKER\'s useEffect--->', props.count);
    setCount(props.count); 
  }, [props.count]);// <-- This one
Run Code Online (Sandbox Code Playgroud)

当组件从组件 DC 获取新值时触发。它将自身的状态设置Joker为 props.count,这会导致组件重新渲染。

然后给出以下输出:

I am JOKER's  render--> 1 // Initial render where Joker receives props from DC
index.js:27 I am JOKER's useEffect---> 2 // The hook runs because props.count changed
index.js:27 I am JOKER's  render--> 2 // Joker rerenders because its state updated.
Run Code Online (Sandbox Code Playgroud)