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?
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.
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.
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.
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.
If you attempt to set state on an unmounted component, you’ll get an error like that.There are two solutions:
Assure Component isMounted : use setstate();
after checking that the component is mounted or not.
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
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With