简体   繁体   English

React Hooks 渲染两次

[英]React Hooks render twice

I define a scene: we have a component that uses parent's props and itself state.我定义了一个场景:我们有一个使用父级道具和自身 state 的组件。

There are two Components DC and JOKER and my step under the below:有两个组件 DC 和 JOKER 以及我在下面的步骤:

  1. click DC's button点击 DC 的按钮
  2. DC setCount DC setCount
  3. JOKER will render with the old state JOKER 将使用旧的 state 进行渲染
  4. running useEffect and setCount运行 useEffect 和 setCount
  5. JOKER does render again JOKER 确实再次渲染

在此处输入图像描述

I want to ask why JOKER render twice(step 3 and 5) and the first render squanders the performance.我想问为什么 JOKER 渲染两次(第 3 步和第 5 步)而第一次渲染会浪费性能。 I just do not want step 3 .我只是不想第 3 步 If in class component I can use componentShouldUpdate to avoid it.如果在 class 组件中,我可以使用 componentShouldUpdate 来避免它。 But Hooks has the same something?但是 Hooks 有同样的东西吗?

My code under the below, or open this website https://jsfiddle.net/stephenkingsley/sw5qnjg7/我的代码在下面,或者打开这个网站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"))

It's an intentional feature of the StrictMode.这是 StrictMode 的一个有意的功能。 This only happens in development, and helps find accidental side effects put into the render phase.这只发生在开发中,有助于发现渲染阶段的意外副作用。 We only do this for components with Hooks because those are more likely to accidentally have side effects in the wrong place.我们只对带有 Hook 的组件执行此操作,因为这些组件更有可能意外地在错误的位置产生副作用。 -- gaearon commented on Mar 9, 2019 ——gaearon 于 2019 年 3 月 9 日发表评论

I'm not sure I understand your question, but here goes.我不确定我是否理解你的问题,但这里有。

When your <DC /> component changes state, it passes the new state value count to the component Joker.当您的<DC />组件更改 state 时,它会将新的 state 值count传递给组件 Joker。 At this point the component will rerender, accounting for the first change.此时组件将重新渲染,考虑到第一次更改。

Then you bind the effect to props.count changes;然后将效果绑定到props.count更改;

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

Which triggers when the component gets the new value from the component DC.当组件从组件 DC 获取新值时触发。 It will set the state of it self Joker to props.count, which causes the component to rerender.它将自己Joker的 state 设置为 props.count,这会导致组件重新渲染。

Which then gives you the following output:然后为您提供以下 output:

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.

If we just want to do the same something alike componentShouldUpdate, we can use useMemo.如果我们只是想做同样的事情,比如 componentShouldUpdate,我们可以使用 useMemo。

function DC() {
  const [count, setCount] = useState(0);
  const [sum, setSum] = useState(0);
  const memoizedJOKER = useMemo(() => <JOKER count={count} />, [count]);
  return (
    <div>
      <button onClick={() => {
        // setCount(count + 1);
        setSum(sum + 1);
        console.log('---click---');
        console.log('\n');
      }}>
        Click me
      </button>
      <p>DC: You clicked {count} times</p>
      <p>now this is {sum} times</p>
      {memoizedJOKER}
    </div>
  );
}

When you click button, JOKER does not render again.当您单击按钮时,JOKER 不会再次渲染。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM