I have a react app where I load images using another component called load-image
.
Now I pass src
to load-image
, it shows a nice loader till image loads, and when its loaded, it shows a nice animation of image.
The problem arises here. I opened the app page, All images start loading. Now user goes to another page, the images are still loading. I can see them loading in the console. Now I get this error in console.
Warning: setState(...): Can only update a mounted or mounting component. This usually means you called setState() on an unmounted component. This is a no-op. Please check the code for the undefined component.
Here is my code.
export default class LoadImage extends React.Component {
constructor() {
super();
this.state = {
isLoaded: false,
isMounted: false,
};
this.onImageLoad = this.onImageLoad.bind(this);
}
componentDidMount() {
const imgSrc = this.props.imageSrc;
const img = new window.Image();
img.onload = this.onImageLoad;
img.src = imgSrc;
this.setState({
isMounted: true,
});
}
componentWillUnmount() {
this.setState({
isMounted: false,
});
}
onImageLoad() {
const self = this;
if (self.state.isMounted === true) {
self.setState({
isLoaded: true,
});
}
}
render() {
const self = this;
const imageClasses = classNames({
'image-loaded': self.state.isLoaded,
'image': true,
});
const imgStyle = {
backgroundImage: 'url("' + self.props.imageSrc + '")',
backgroundSize: 'cover',
backgroundPosition: 'center',
backgroundRepeat: 'no-repeat',
width: 'inherit',
height: 'inherit',
};
return (
<div className="image-loader">
<div style={ imgStyle } className={ imageClasses }>
</div>
</div>
);
}
}
How can i cancel older request so that they don't update state after unmounting. I am already using state to check if component is mounted or not. Thanks.
The componentWillUnmount() method allows us to execute the React code when the component gets destroyed or unmounted from the DOM (Document Object Model). This method is called during the Unmounting phase of the React Life-cycle i.e before the component gets unmounted.
The useEffect() hook is called when the component is mounted and sets the mounted. current value to true . The return function from the useEffect() hook is called when the component is unmounted and sets the mounted. current value to false .
The componentWillUnmount method is called when the component is about to be removed from the DOM.
You can just unmount it conditionally. All you have to do is remove it from the DOM in order to unmount it. As long as renderMyComponent = true , the component will render. If you set renderMyComponent = false , it will unmount from the DOM.
You can change the callback while the image is still loading. In componentWillUnmount
, set this.img.onload
to a function that does nothing.
componentDidMount() {
const imgSrc = this.props.imageSrc;
this.img = new window.Image();
this.img.src = imgSrc;
this.img.onload = this.onImageLoad;
}
componentWillUnmount() {
if ( ! this.img ) {
return;
}
this.img.onload = function(){};
delete this.img;
}
Source: https://github.com/Automattic/wp-calypso/blob/master/client/components/image-preloader/index.jsx
No need for isMounted() if you take this approach.
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