@dcasia/react-lazy-load-image-component-improved
Version:
React Component to lazy load images using a HOC to track window scroll position.
172 lines (151 loc) • 3.25 kB
JSX
import React from 'react';
import { PropTypes } from 'prop-types';
import LazyLoadComponent from './LazyLoadComponent.jsx';
class LazyLoadImage extends React.Component {
constructor(props) {
super(props);
this.state = {
loaded: false,
};
}
onImageLoad() {
if (this.state.loaded) {
return null;
}
return () => {
this.props.afterLoad();
this.setState({
loaded: true,
});
};
}
getImg() {
const {
afterLoad,
beforeLoad,
delayMethod,
delayTime,
effect,
placeholder,
placeholderSrc,
scrollPosition,
threshold,
useIntersectionObserver,
visibleByDefault,
wrapperClassName,
wrapperProps,
...imgProps
} = this.props;
return <img onLoad={this.onImageLoad()} {...imgProps} />;
}
getLazyLoadImage() {
const {
beforeLoad,
className,
delayMethod,
delayTime,
height,
placeholder,
scrollPosition,
style,
threshold,
useIntersectionObserver,
visibleByDefault,
width,
} = this.props;
return (
<LazyLoadComponent
beforeLoad={beforeLoad}
className={className}
delayMethod={delayMethod}
delayTime={delayTime}
height={height}
placeholder={placeholder}
scrollPosition={scrollPosition}
style={style}
threshold={threshold}
useIntersectionObserver={useIntersectionObserver}
visibleByDefault={visibleByDefault}
width={width}
>
{this.getImg()}
</LazyLoadComponent>
);
}
getWrappedLazyLoadImage(lazyLoadImage) {
const {
effect,
height,
placeholderSrc,
width,
wrapperClassName,
wrapperProps,
} = this.props;
const { loaded } = this.state;
const loadedClassName = loaded ? ' lazy-load-image-loaded' : '';
return (
<span
className={
wrapperClassName +
' lazy-load-image-background ' +
effect +
loadedClassName
}
style={{
backgroundImage:
placeholderSrc ? `url(${placeholderSrc})` : null,
backgroundSize:
placeholderSrc ? '100% 100%' : null,
color: 'transparent',
display: 'inline-block',
height: height,
width: width,
}}
{...wrapperProps}
>
{lazyLoadImage}
</span>
);
}
render() {
const {
effect,
placeholderSrc,
visibleByDefault,
wrapperClassName,
wrapperProps,
} = this.props;
const lazyLoadImage = this.getLazyLoadImage();
const needsWrapper = (effect || placeholderSrc) && !visibleByDefault;
if (!needsWrapper && !wrapperClassName && !wrapperProps) {
return lazyLoadImage;
}
return this.getWrappedLazyLoadImage(lazyLoadImage);
}
}
LazyLoadImage.propTypes = {
afterLoad: PropTypes.func,
beforeLoad: PropTypes.func,
delayMethod: PropTypes.string,
delayTime: PropTypes.number,
effect: PropTypes.string,
placeholderSrc: PropTypes.string,
threshold: PropTypes.number,
useIntersectionObserver: PropTypes.bool,
visibleByDefault: PropTypes.bool,
wrapperClassName: PropTypes.string,
wrapperProps: PropTypes.object,
};
LazyLoadImage.defaultProps = {
afterLoad: () => ({}),
beforeLoad: () => ({}),
delayMethod: 'throttle',
delayTime: 300,
effect: '',
placeholderSrc: null,
threshold: 100,
useIntersectionObserver: true,
visibleByDefault: false,
wrapperClassName: '',
};
export default LazyLoadImage;