@sirbrillig/ensured-image
Version:
React component to reload an image if it fails.
85 lines (73 loc) • 2.06 kB
JavaScript
/* globals setTimeout */
const React = require( 'react' );
const PropTypes = require( 'prop-types' );
const secsToMs = ( secs ) => secs * 1000;
const el = React.createElement;
class EnsuredImage extends React.Component {
constructor( props ) {
super( props );
this.state = { didLoadFail: false };
this.handleFailedImage = this.handleFailedImage.bind( this );
this.retryImage = this.retryImage.bind( this );
}
retryImage() {
this.setState( { didLoadFail: false } );
}
handleFailedImage( retryAfter ) {
this.setState( { didLoadFail: true } );
this.props.setTimeout( this.retryImage, retryAfter );
this.props.onError && this.props.onError();
}
render() {
const { src, retryAfter, className, onClick, alt, id, sizes, srcSet, title } = this.props;
if ( this.state.didLoadFail ) {
return el( this.props.PlaceholderComponent );
}
const onError = () => this.handleFailedImage( retryAfter );
return el( this.props.ImageComponent, { src, onError, className, onClick, alt, id, sizes, srcSet, title } );
}
}
EnsuredImage.propTypes = {
// img props
src: PropTypes.string.isRequired,
className: PropTypes.string,
onClick: PropTypes.func,
onError: PropTypes.func,
alt: PropTypes.string,
id: PropTypes.string,
sizes: PropTypes.string,
srcSet: PropTypes.string,
title: PropTypes.string,
// Special props
retryAfter: PropTypes.number,
setTimeout: PropTypes.func,
ImageComponent: PropTypes.func,
PlaceholderComponent: PropTypes.func,
};
EnsuredImage.defaultProps = {
retryAfter: secsToMs( 60 ),
setTimeout: ( callBack, timeUntil ) => setTimeout( callBack, timeUntil ),
ImageComponent,
PlaceholderComponent,
};
function ImageComponent( { src, onError, className, onClick, alt, id, sizes, srcSet, title } ) {
return el( 'img', {
className,
src,
onError,
onClick,
alt,
id,
sizes,
srcSet,
title
} );
}
function PlaceholderComponent() {
return el(
'svg',
{ width: '33', height: '33' },
el( 'circle', { cx: '16', cy: '16', r: '15', fill: 'orange' } )
);
}
module.exports = EnsuredImage;