Render Component if image src is valid

时间:2016-07-11 20:05:02

标签: javascript reactjs

I want to render an Image component, but before that I need to check whether the URL is not broken.

My approach is not giving any errors and the onload function is loading. Though, I assume I am doing (or not doing) the return of the component incorrectly.

Could someone advise what is wrong?


~UPDATE~ I even tried using a renderImage method to ensure that I am using the return() syntax...

    renderImage(mediaObj) {
        let image = document.createElement('img');
        image.src = mediaObj.url;
        console.log("mediaObj", image);
        image.onload = function() {
            console.log("onload");
            return (
                <Image
                    key={`carousel_${mediaObj.media_id}`}
                    {...this.props}
                    mediaObj={mediaObj}/>
            );
        };

    }

and map...

this.props.mediaObjects.map(mediaObj => this.renderImage(mediaObj))


Here is my render method:

render()

render () {
    return (
        <div id="galleryImages_outerWrapper">
            <div id="galleryImages_innerWrapper" className="flexParent flexRowWrap">
                {
                    this.props.mediaObjects.map(mediaObj => {
                        let image = document.createElement('img');
                        image.onload = () => {
                            <Image
                                key={`carousel_${mediaObj.media_id}`}
                                {...this.props}
                                mediaObj={mediaObj}/>
                        };

                        image.src = mediaObj.url;
                    })
                }
            </div>
        </div>
    );
}

1 个答案:

答案 0 :(得分:2)

image.onload is asynchronous, so if you want to check urls validity, you have to wait until all callbacks are done, and only after it render the component. Make a chain of promises resolving urls, and after all of them are resolved update the component state. Here is a fiddle with working example:

componentWillMount: function() {  
  let promises = [];
  mediaObjects.forEach(mediaObj =>
    promises.push(
      new Promise((resolve, reject) => {
        let image = document.createElement('img');
        image.src = mediaObj.url;
        image.onload = () => {
          mediaObj.validUrl = true;
          resolve(mediaObj)
        }
        image.onerror = () => {
          mediaObj.validUrl = false;
          resolve(mediaObj)
        }
      })
  ))
  Promise
    .all(promises)
    .then((values) => {
      this.setState({mediaObjs: values});
    })
},

render: function() {
  if (this.state.mediaObjs) {
    let images = this.state.mediaObjs
      .filter((mediaObj) => {
        return mediaObj.validUrl
       })
       .map((mediaObj, i) => (
         <span key={i}><img src={mediaObj.url}/></span>
       ))
    return <div>{images}</div>
  } else {
    return (<div>Loading</div>)
  }  

}