首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >React setState inside

React setState inside
EN

Stack Overflow用户
提问于 2016-08-09 07:58:22
回答 2查看 5K关注 0票数 5

我正在为图像构建一个懒散的组件。但我对设定状态有问题。我得到的只能更新一个挂载或挂载组件错误,但是我在componentDidMount中使用setState,这应该允许我避免这样的错误。

这是我的密码:

代码语言:javascript
复制
export default class Images extends React.Component {
    constructor(props) {
        super(props);

        this.element = null;

        this.state = {
            loaded: false,
            height: 0
        };
    }

    componentDidMount() {
        this.element = findDOMNode(this);

        this.loadImage();
    }

    getDimensions() {
        const w = this.element.offsetWidth;

        let initw = 0;
        let inith = 0;

        let result;

        const img = new Image();
        img.src = this.props.url;

        img.onload = (e) => {
            initw = e.path[0].width;
            inith = e.path[0].height;

            result = (w / initw) * inith;

            setTimeout(() => {
                this.setState({
                    loaded: true,
                    height: `${result}px`
                });
            });
        }
    }

    loadImage() {
        _scrolling.add([this.element], () => {
            if (this.element.classList.contains(_scrolling.classes.coming)) { // the image is visible
                this.getDimensions();
            }
        });
    }

    render() {
        const classes = this.state.loaded ? `${this.props.parentClass}__image--loaded` : null;
        const styles = this.state.loaded ? {
            maxHeight: this.state.height, minHeight: this.state.height, overflow: 'hidden'
        } : null;

        return (
            <div className={`${this.props.parentClass}__image ${classes}`} style={styles}>
                {this.state.loaded ?
                    <img
                        className={`${this.props.parentClass}__img`}
                        src={this.props.url}
                        title={this.props.title}
                        alt={this.props.title}
                    />
                    : null
                }
            </div>
        )
    }

我相信问题在img.onload内部,但我不知道如何实现这一点。我该怎么办?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-08-09 08:19:56

如果您试图在未挂载的组件上设置状态,您将得到一个错误,比如that.There是两种解决方案:

  1. 确保组件isMounted :在检查组件是否已安装后使用setstate();
  2. 中止请求:当组件卸载时,我们可以丢弃请求,这样就不会调用回调。要做到这一点,我们将利用另一个React生命周期挂钩,componentWillUnmount
票数 4
EN

Stack Overflow用户

发布于 2016-08-09 08:29:14

img.onload处理程序似乎是在未挂载的Images组件实例上被调用的。

图像加载是异步的,需要一些时间。当它最终完成并且img.onload处理程序被调用时,无法保证您的组件仍然被挂载。

您必须使用componentWillUnmount并确保:

  • 在组件卸载之前取消图像加载,或
  • 跟踪组件的挂载状态,并检查一旦调用处理程序它是否已挂载

有关检查组件是否已挂载的更多信息:https://facebook.github.io/react/blog/2015/12/16/ismounted-antipattern.html

解决方案:取消图像加载

代码语言:javascript
复制
export default class Images extends React.Component {
    constructor(props) {
        super(props);

        this.element = null;

        this.state = {
            loaded: false,
            height: 0
        };

        this.images = []; // We’ll store references to the Image objects here.
    }

    componentDidMount() {
        this.element = findDOMNode(this);

        this.loadImage();
    }

    componentWillUnmount() {
        this.images.forEach(img => img.src = ''); // Cancel the loading of images.
    }

    getDimensions() {
        const w = this.element.offsetWidth;

        let initw = 0;
        let inith = 0;

        let result;

        const img = new Image();
        img.src = this.props.url;

        img.onload = (e) => {
            initw = e.path[0].width;
            inith = e.path[0].height;

            result = (w / initw) * inith;

            setTimeout(() => {
                this.setState({
                    loaded: true,
                    height: `${result}px`
                });
            });
        }

        this.images.push(img); // Store the reference.
    }

    loadImage() {
        _scrolling.add([this.element], () => {
            if (this.element.classList.contains(_scrolling.classes.coming)) { // the image is visible
                this.getDimensions();
            }
        });
    }

    render() {
        const classes = this.state.loaded ? `${this.props.parentClass}__image--loaded` : null;
        const styles = this.state.loaded ? {
            maxHeight: this.state.height, minHeight: this.state.height, overflow: 'hidden'
        } : null;

        return (
            <div className={`${this.props.parentClass}__image ${classes}`} style={styles}>
                {this.state.loaded ?
                    <img
                        className={`${this.props.parentClass}__img`}
                        src={this.props.url}
                        title={this.props.title}
                        alt={this.props.title}
                    />
                    : null
                }
            </div>
        )
    }
}

我从:https://stackoverflow.com/a/5278475/594458复制了图像取消

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/38845144

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档