Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React - setState inside componentDidMount

Tags:

reactjs

I am building a lazyloading component for images. But I have a problem with setting state. I'm getting Can only update a mounted or mounting component error, but I am using setState inside componentDidMount, which should allow me to avoid such errors.

Here's my code:

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

I belive the problem lies within img.onload, but I don't know how to achieve this otherwise. What should I do?

like image 216
Tomek Buszewski Avatar asked Aug 09 '16 07:08

Tomek Buszewski


People also ask

Is it OK to setState in componentDidMount?

You may call setState() immediately in componentDidMount() . It will trigger an extra rendering, but it will happen before the browser updates the screen. This guarantees that even though the render() will be called twice in this case, the user won't see the intermediate state.

Can we update state in componentDidMount lifecycle method?

componentDidMount() method is the perfect place, where we can call the setState() method to change the state of our application and render() the updated data loaded JSX.

Can I use setState in componentDidUpdate?

You may call setState() immediately in componentDidUpdate() but note that it must be wrapped in a condition like in the example above, or you'll cause an infinite loop. It would also cause an extra re-rendering which, while not visible to the user, can affect the component performance.

Can we setState in componentWillUnmount?

ReactJS componentWillUnmount() Method Tip: Never call setState() in componentWillUnmount() method. Project Structure: It will look like the following. Example: In this example, we are going to build a name color application that changes the color of the text when the component is rendered in the DOM tree. App.


1 Answers

If you attempt to set state on an unmounted component, you’ll get an error like that.There are two solutions:

  1. Assure Component isMounted : use setstate(); after checking that the component is mounted or not.

  2. Abort the Request: When the component unmounts, we can just throw away the request so the callback is never invoked. To do this, we’ll take advantage of another React lifecycle hook, componentWillUnmount.

like image 184
Istiak Morsalin Avatar answered Nov 15 '22 11:11

Istiak Morsalin