使 React useEffect 钩子不在初始渲染上运行 [英] Make React useEffect hook not run on initial render

查看:28
本文介绍了使 React useEffect 钩子不在初始渲染上运行的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

根据文档:

<块引用>

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

我们可以使用新的 useEffect() 钩子来模拟 componentDidUpdate(),但看起来 useEffect() 正在被运行每次渲染,即使是第一次.如何让它不在初始渲染中运行?

正如您在下面的示例中看到的,componentDidUpdateFunction 在初始渲染期间打印,但 componentDidUpdateClass 在初始渲染期间未打印.

function ComponentDidUpdateFunction() {const [count, setCount] = React.useState(0);React.useEffect(() => {console.log("componentDidUpdateFunction");});返回 (<div><p>componentDidUpdateFunction: {count} 次</p><按钮onClick={() =>{设置计数(计数 + 1);}}>点击我

);}class ComponentDidUpdateClass 扩展 React.Component {构造函数(道具){超级(道具);this.state = {计数:0,};}componentDidUpdate() {console.log("componentDidUpdateClass");}使成为() {返回 (<div><p>componentDidUpdateClass:{this.state.count} 次</p><按钮onClick={() =>{this.setState({ 计数: this.state.count + 1 });}}>点击我

);}}ReactDOM.render(<div><ComponentDidUpdateFunction/><ComponentDidUpdateClass/>

,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>

解决方案

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

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

示例

const { useState, useRef, useLayoutEffect } = React;函数 ComponentDidUpdateFunction() {const [count, setCount] = useState(0);const firstUpdate = useRef(true);useLayoutEffect(() => {如果(firstUpdate.current){firstUpdate.current = false;返回;}console.log("componentDidUpdateFunction");});返回 (<div><p>componentDidUpdateFunction: {count} 次</p><按钮onClick={() =>{设置计数(计数 + 1);}}>点击我

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

According to the docs:

componentDidUpdate() is invoked immediately after updating occurs. This method is not called for the initial render.

We can use the new useEffect() hook to simulate componentDidUpdate(), but it seems like useEffect() is being ran after every render, even the first time. How do I get it to not run on initial render?

As you can see in the example below, componentDidUpdateFunction is printed during the initial render but componentDidUpdateClass was not printed during the initial render.

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>

解决方案

We can use the useRef hook to store any mutable value we like, so we could use that to keep track of if it's the first time the useEffect function is being run.

If we want the effect to run in the same phase that componentDidUpdate does, we can use useLayoutEffect instead.

Example

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>

这篇关于使 React useEffect 钩子不在初始渲染上运行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
前端开发最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆