使 React useEffect 钩子不在初始渲染时运行

问题描述

我们可以使用useRef钩子来存储我们喜欢的任何可变值,因此我们可以使用它来跟踪useEffect函数是否是第一次运行。

如果我们希望效果在相同的阶段运行componentDidUpdate,我们可以使用useLayoutEffect

const { useState, useRef, useLayoutEffect } = React;



function ComponentDidUpdateFunction() {

  const [count, setCount] = useState(0);



  const firstUpdate = useRef(true);

  useLayoutEffect(() => {

    if (firstUpdate.current) {

      firstUpdate.current = false;

      return;

    }



    console.log("componentDidUpdateFunction");

  });



  return (

    <div>

      <p>componentDidUpdateFunction: {count} times</p>

      <button

        onClick={() => {

          setCount(count + 1);

        }}

      >

        Click Me

      </button>

    </div>

  );

}



ReactDOM.render(

  <ComponentDidUpdateFunction />,

  document.getElementById("app")

);


<script src="https://unpkg.com/react@16.7.0-alpha.0/umd/react.development.js"></script>

<script src="https://unpkg.com/react-dom@16.7.0-alpha.0/umd/react-dom.development.js"></script>



<div id="app"></div>

解决方法

根据文档:

componentDidUpdate()在更新发生后立即调用。初始渲染不调用此方法。

我们可以使用新的useEffect()钩子来模拟componentDidUpdate(),但它似乎useEffect()是在每次渲染之后运行,即使是第一次。如何让它不在初始渲染时运行?

正如您在下面的示例中所见,componentDidUpdateFunction在初始渲染期间打印,但在初始渲染componentDidUpdateClass期间未打印。

function ComponentDidUpdateFunction() {

  const [count,setCount] = React.useState(0);

  React.useEffect(() => {

    console.log("componentDidUpdateFunction");

  });



  return (

    <div>

      <p>componentDidUpdateFunction: {count} times</p>

      <button

        onClick={() => {

          setCount(count + 1);

        }}

      >

        Click Me

      </button>

    </div>

  );

}



class ComponentDidUpdateClass extends React.Component {

  constructor(props) {

    super(props);

    this.state = {

      count: 0,};

  }



  componentDidUpdate() {

    console.log("componentDidUpdateClass");

  }



  render() {

    return (

      <div>

        <p>componentDidUpdateClass: {this.state.count} times</p>

        <button

          onClick={() => {

            this.setState({ count: this.state.count + 1 });

          }}

        >

          Click Me

        </button>

      </div>

    );

  }

}



ReactDOM.render(

  <div>

    <ComponentDidUpdateFunction />

    <ComponentDidUpdateClass />

  </div>,document.querySelector("#app")

);


<script src="https://unpkg.com/react@16.7.0-alpha.0/umd/react.development.js"></script>

<script src="https://unpkg.com/react-dom@16.7.0-alpha.0/umd/react-dom.development.js"></script>



<div id="app"></div>