【问题标题】:Warning react : setState(...): Can only update a mounted or mounting component警告反应:setState(...):只能更新已安装或正在安装的组件
【发布时间】:2019-08-15 20:23:26
【问题描述】:

警告:setState(...):只能更新已安装或正在安装的组件。这通常意味着您在未安装的组件上调用了 setState()。这是无操作的。

这是一个反应应用程序,其中横幅固定在屏幕上并传递随机图像。它的编写方式正在生成有问题的警告。

import React from "react";
import Lightbox from "react-image-lightbox";
import logo from "./logo.png";

class Banner extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      images: [],
      currentImage: logo,
      isOpen: false,
      sidebarOpen: true
    };
  }

  async componentWillMount() {
    await this.getBanners();
    this.setState({ currentImage: this.state.images[0].url });

    setInterval(async () => {
      await this.getBanners();
    }, 300000);

    let i = 0;
    setInterval(
      () => {
        this.setState({ currentImage: this.state.images[i].url });
        if (i >= this.state.images.length - 1) {
          i = 0;
        } else {
          i++;
        }
      },
      10000,
      i
    );
  }

  async getBanners() {
    const data = await (await fetch("/api/banners/active")).json();
    if (data.true) {
      this.setState({ images: data.true });
    }
  }

  render() {
    const { isOpen } = this.state;

    return (
      <div>
        {isOpen && (
          <Lightbox
            mainSrc={this.state.currentImage}
            onCloseRequest={() => this.setState({ isOpen: false })}
          />
        )}
        <footer>
          <a>
            <img
              width={270}
              height="200"
              src={this.state.currentImage}
              onClick={() => this.setState({ isOpen: true })}
              alt="idk"
            />
          </a>
        </footer>
      </div>
    );
  }
}

export default Banner;

谁能帮助改进这段代码?

【问题讨论】:

  • 你的 setIntervals 将永远发生,所以如果它被挂载/卸载,你会得到很多错误和内存泄漏。
  • 任何答案对您有用吗?如果是这种情况,请考虑 accepting one of them

标签: javascript reactjs redux


【解决方案1】:

您可以将setInterval 返回的数字放在您的实例上,并在componentWillUnmount 中停止带有clearInterval 的间隔,以便在卸载组件后它们不会继续运行。

class Banner extends React.Component {
  constructor(props) {
    super(props);

    this.bannerInterval = null;
    this.currentImageInterval = null;
    this.state = {
      images: [],
      currentImage: logo,
      isOpen: false,
      sidebarOpen: true
    };
  }

  async componentDidMount() {
    await this.getBanners();
    this.setState({ currentImage: this.state.images[0].url });

    this.bannerInterval = setInterval(async () => {
      await this.getBanners();
    }, 300000);

    let i = 0;
    this.currentImageInterval = setInterval(
      () => {
        this.setState({ currentImage: this.state.images[i].url });
        if (i >= this.state.images.length - 1) {
          i = 0;
        } else {
          i++;
        }
      },
      10000,
      i
    );
  }

  componentWillUnmount() {
    clearInterval(this.bannerInterval);
    clearInterval(this.currentImageInterval);
  }

  // ...
}

【讨论】:

  • 问题是组件永远不会被卸载。它是屏幕上的固定横幅。
【解决方案2】:

将此模板用于任何具有状态的基于类的组件:

忘记了 setState(),使用 setComponentState 声明:

class MyComponent extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      // other fields...
      isUnmounted: false,
    };
  }

  componentWillUnmount() {
    this.setState({ isUnmounted: true });
  }

  setComponentState = (values) => {
    if (!this.state.isUnmounted) this.setState(values);
  };
}

【讨论】:

    猜你喜欢
    • 2017-04-26
    • 2016-10-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-02
    • 1970-01-01
    • 2016-09-25
    • 2018-02-06
    相关资源
    最近更新 更多