对已安装/未安装的组件执行React,setState警告

时间:2017-08-21 15:09:09

标签: javascript reactjs

我有一个反应组件,我正在逐步为我的应用程序加载我的图像,这对我来说非常有用。但是,当我在页面上使用它来加载图像时,我看到了一个错误:

  

warning.js:35警告:setState(...):只能更新已安装或安装的组件。这通常意味着您在已卸载的组件上调用了setState()。这是一个无操作。

多次 - 对于每个被调用的图像看起来像一次。由于图像组件仍然有效,它似乎没有真正影响任何东西。我想知道如何摆脱这个错误,我无法弄清楚如何。

所以这是我的组成部分:

import React, { PropTypes } from 'react';

require('./progressive-image.scss');

export default class ProgressiveImage extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      loaded: false,
      image: props.smallImg
    };

    this.loadImage = this.loadImage.bind(this);
    this.onLoad = this.onLoad.bind(this);
    this.onError = this.onError.bind(this);
    this.image = undefined;
  }

  componentDidMount() {
    const { largeImg } = this.props;
    this.loadImage(largeImg);
  }

  onError(err) {
    console.warn('Error loading progressive image :', err);
  }

  onLoad() {
    this.setState({
      loaded: true,
      image: this.image.src
    });
  }

  componentDidUpdate(nextProps) {
    const { largeImg, smallImg } = nextProps;

    if (largeImg !== this.props.largeImg) {
      this.setState({ loaded: false, image: smallImg }, () => {
        this.loadImage(largeImg);
      });
    }
  }


  loadImage(src) {
    if (this.image) {
      this.image.onload = null;
      this.image.onerror = null;
    }

    const image = new Image();
    this.image = image;
    image.onload = this.onLoad;
    image.onerror = this.onError;
    image.src = src;
  }

  render() {
    const imgStyle = { 'paddingBottom': this.props.heightRatio };
    const { imgAlt, imgTitle } = this.props;

    return (
      <div className={`progressive-placeholder ${this.state.loaded ? 'loaded' : ''}`}>
        {this.state.loaded &&
          <img
            alt={imgAlt}
            className={`loaded`}
            src={this.state.image}
            title={imgTitle}
             />
        }
        <img className={`img-small ${!this.state.loaded ? 'loaded' : ''}`} src={this.state.image} alt="placeholder image for loading"/>
        <div style={imgStyle} ></div>
      </div>
    );
  }
}

ProgressiveImage.displayName = 'ProgressiveImage';

ProgressiveImage.propTypes = {
  bgColor: PropTypes.string,
  heightRatio: PropTypes.string.isRequired,
  largeImg: PropTypes.string.isRequired,
  smallImg: PropTypes.string.isRequired,
  imgAlt: PropTypes.string,
  imgTitle: PropTypes.string,
};

因此,调用setState的唯一时间是调用onLoadcomponentDidUpdate时。我的想法是,因为它只被调用mount并且确实更新了它不应该得到这个错误。寻找有关如何清除此错误的任何见解,因为它让我感到困惑。如果需要任何其他信息,我很乐意提供。

1 个答案:

答案 0 :(得分:1)

问题是image.onload中的回调可以在任意随机点调用

    image.onload = this.onLoad;

在您的组件呈现时,可能会调用this.onLoad

问题在于,因为在您加载外部图片资源时会调用this.onLoad,所以当您执行this.setState时,您的组件可能会呈现,会导致错误

为了解决这个问题,我建议将loaded / image值设置在本地Component状态之外,而使用dispatch将其设置为全局状态redux 1}}。