0

I have a React + Rails app and the current S3 server issues made me realize that I don't have a proper fallback mechanism when data can't be pulled from s3. I'm trying to make it work with my locally stored images for the moment and I plan on adding it the same way to my other image tags.

My img is as follows:

errorLink() {
  this.onError = null;
  this.src = '/img/icons/static/credentials.svg';
}

<img alt="Icon for credentials and experience" src="/img/icons/static/credentials123.svg" onError={this.errorLink.bind(this)()}/>

the src inside the image pointing to credentials123.svg is a dummy and I've added it specifically to raise the error. But it's not updating the src of my image. How can I achieve this in react? I'd rather not show broken image links to my users next time during an Amazon outage

anonn023432
  • 2,940
  • 6
  • 31
  • 63

2 Answers2

1

One of the many many solutions (since it is really based on your inner React project structure). You just keep your image url in a state somewhere as a default image. Once you get your proper image url from S3 then you will replace default one in state with a new one you got.

const DEFAULT_IMAGE = '/img/icons/static/default.svg';

class MyComponent extends React.Component {
    constructor(props) {
        super(props);

        this.state = {
            url: DEFAULT_IMAGE
        };
    }

    render() {
        return (
            {/* ... some UI here ... */}

            <img 
                alt="Icon for credentials and experience" 
                src={this.state.url}
            />
        );
    }

    // ....

    _someAsync = () => {
        // some async logic here

        // In here in 5 seconds state will be updated by replacing default url
        // with new url image link
        setTimeout(() => this.setState({ 
            loaded: true, 
            url: '/img/icons/static/credentials.svg'
        }), 5000);
    };
}
anvk
  • 1,183
  • 8
  • 10
  • But then in case I have a lot of images on a single page, then wouldn't I have to save the url of each image in a separate state? – anonn023432 Feb 28 '17 at 21:53
  • If the image url is STATIC property(always the same or always the same but only changes to a specific value when async function is done) then you do NOT need to save url in state. If the image url is DYNAMIC property (you retrieve it from API or it changes based on some interactions) then you WANT to save url in state and change it as a variable when required. – anvk Feb 28 '17 at 22:01
  • It is a dynamic property as I retrieve it from Amazon S3. And although your solution is perfect for my question, but would it be a good idea to use this method on a page where I'm loading a catalog of items and thus 50+ images – anonn023432 Feb 28 '17 at 22:16
  • Then you save array of those urls and render your images http://stackoverflow.com/questions/25646502/how-to-render-repeating-elements. Or if you REALLY like adventures (this is probably very bad practice) you can have a `ref` to some div element in your UI and you can generate some content and inject it into that div once you get image urls. Also what is a problem of keeping data for 50 images on the page. I work with states and UI which uses LOTS of data to render and it is fine. – anvk Feb 28 '17 at 22:19
  • If you are worried about having too many images you might want to research into Infinite Scrolling. – anvk Feb 28 '17 at 22:26
0

One simple way to do it is

Make sure you put/set the value this.state = {image: 'image-to-load.jpeg'} in render.

<img src={this.state.image} ref={image => this.image = image} onError={() => this.image.src = '/alternate-failover.jpg'

It worked for me. Small, precise, and reliable code

Ref: https://stackoverflow.com/a/42848501/10231115

Vihar Manchala
  • 667
  • 6
  • 14