Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React img not immediately changing when src changes. How can I fix this?

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;
like image 503
Alex Avatar asked Jun 05 '18 01:06

Alex


People also ask

How do you handle image error in React?

To replace img src onerror with React, we set the fallback image URL when there's an error loading the image. to create the imgSrc state. We set imgSrc to src initially. Then we add the img element with an onError prop that's set to the onError function.

How do I bind an image in React?

Option 1: import the image into the component Put the image file somewhere under the src folder. This alone will not automatically make it available, so you have to import the image into the React component where you're using it. import companyLogo from './path/to/logo.


2 Answers

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>
like image 125
Jahid Hasan Avatar answered Nov 07 '22 08:11

Jahid Hasan


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>

like image 22
Alex Avatar answered Nov 07 '22 08:11

Alex