Reputation: 450
I have a basic <img>
with a src.
<img src={src} />
If I change the src from say /1.jpg
to /2.jpg
and the new image takes 1 second to load, React will continue to show /1.jpg
until the new image is loaded.
What I want is for the old image to be discarded while the new image is being loaded. (e.g. display: none)
Any idea how to accomplish this? Ideally without conditional rendering, because I still need to use onLoad
and onError
EDIT: Here's some more code. It's a little more complicated than my question, but I'm just trying to add some loading and error state to the image.
I have a button that calls this onClick
this.props.history.push('/${page + 1}');
This is the image component, where src is based on the page
from the URL.
import React, { Component } from 'react';
import CenteredLoading from 'components/loading/CenteredLoading';
type Props = { src: string };
type State = {
status: 'LOADING' | 'LOADED' | 'FAILED',
};
class ImageWithLoader extends Component<Props, State> {
state = {
status: 'LOADING',
};
handleImageLoad = () => {
this.setState({ status: 'LOADED' });
console.error('image loaded');
};
handleImageError = () => {
this.setState({ status: 'FAILED' });
console.error('image error');
};
render() {
const { src, ...otherProps } = this.props;
const { status } = this.state;
return (
<React.Fragment>
<img
{...otherProps}
onLoad={this.handleImageLoad}
onError={this.handleImageError}
src={src}
/>
{status === 'LOADING' && <CenteredLoading />}
{status === 'FAILED' && <p>error</p>}
</React.Fragment>
);
}
}
export default ImageWithLoader;
Upvotes: 21
Views: 14978
Reputation: 653
Just add key attribute to your image tag and assign some unique value to key attribute like image source.
<img src={image_source} key={image_source}></img>
Upvotes: 50
Reputation: 450
Made my own workaround.
I believe because react isn't mounting a new component (i.e. <img>
), it's not going to update to the new image until it's finished loading.
What I did was check if the src
changed in componentDidUpdate
and change the status to LOADING
. Then I set img style to display: none
while its status was LOADING
.
EDIT: Also, by manually setting my own key, I can force React to re-render the <img>
Upvotes: 7