0

I need to display a fallback image when the original url request returns with a 404. The image wont return an error until it's called upon and I can't figure out how to access that 404 to redirect it.

the fallback image has been imported from my local files

My if statement in checkImg = (props) => {} is completely disregarded as it is now.

export default class FirstListPage extends React.Component{

  checkImg = (product) => {
    if(product.imgurl === null){
      return <img src={fallback} alt='default' />                        
    }
    return <img src={product.imgurl} alt='first choice' />
  }

  render(){                
    if (this.props.firstList.data === undefined){
      return null
    }        
    return(
      <div className='card-wrapper'>                        
         {this.props.firstList.data.map(product => 
            <div className='card' 
               key={product.id}>                                                
                 {this.checkImg(product)}                                                
                <h3>{product.title}</h3>
                <p>{product.description}</p>
            </div>
          )}
      </div>
    )                        
  }
}

The only other thing I can think of would be to modify my .catch but I cant wrap my head around how I would specify such a case.

App.js

 componentDidMount() {         
        Promise.all([
            fetch(`${config.API_ENDPOINT}/first`),
            fetch(`${config.API_ENDPOINT}/second`),
            fetch(`${config.API_ENDPOINT}/third`)
        ])
        .then( ([firstRes, secondRes, thirdRes]) => {
            if (!firstRes.ok) 
                return firstRes.json()
                    .then( e => Promise.reject(e))

            if (!secondRes.ok) 
                return secondRes.json()
                    .then(e => Promise.reject(e))

            if (!thirdRes.ok) 
                return thirdRes.json()
                    .then(e => Promise.reject(e))

            return Promise.all([ firstRes.json(), secondRes.json(), thirdRes.json() ])
        })
        .then(([first, second, third]) => { this.setState({firstList, secondList, thirdList}) })        
        .catch(error => { console.error({error}) }) 
    }

Data example

  firstList: {
    itemsPerPage: 6,
    pages: 12,
    data: [
      {
        id: 1,
        imgurl:'https://website.com/image.jpg',
        title: 'shoes',
        description: 'desc here'
      },
    ]
  }

yeahhhmat
  • 41
  • 1
  • 8
  • If the image doesn't have an URL how will the response look like? – Ramesh Reddy Mar 15 '20 at 08:11
  • In `checkImg` function you're using `src={fallback}` where is fallback coming from? – Ramesh Reddy Mar 15 '20 at 08:14
  • all the images will have urls, some will be broken and return a 404 in the console, and renders the alt text. the fallback has been imported from my local files. I will update the post to avoid confusion. – yeahhhmat Mar 15 '20 at 08:14
  • See [this](https://stackoverflow.com/questions/3984287/how-to-show-alternate-image-if-source-image-is-not-found-onerror-working-in-ie/9891041#9891041) and the accepted answer in [this](https://stackoverflow.com/questions/1630451/is-there-a-way-to-designate-multiple-image-sources-in-html-javascript) – Ramesh Reddy Mar 15 '20 at 08:17

2 Answers2

1

Write your custom image component with error handling using onError handler.

Save isError into your component state and in case of error show static image static/404.png

import React from "react";

class ImageComponent extends React.Component {
  constructor(props) {
    super(props);
    this.state = { imageStatus: "loading", error: false };
  }

  handleImageLoaded() {
    this.setState({ imageStatus: "loaded", error: false });
  }

  handleImageError() {
    this.setState({ imageStatus: "failed to load", error: true });
  }

  render() {
    return (
      <div>
        <img
          src={this.state.error ? 'static/404.png' : this.props.imageUrl}
          onLoad={this.handleImageLoaded.bind(this)}
          onError={this.handleImageError.bind(this)}
        />
        {this.state.imageStatus}
      </div>
    );
  }
}

export default ImageComponent;
JaLe
  • 409
  • 3
  • 13
0

You can use onError prop. And update the state on onError.

handleImageError = () => {
this.setState({imageSrcExist: false})
}

checkImg = (product) => {
    return <img src={this.state.imageSrcExist ? product.imgurl : fallbackUrl} onError={this.handleImageError} alt='first choice' />
}
sakpal
  • 28
  • 4