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?
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))
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>
);
}
答案 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>)
}
}