Skip to content

Commit 4a314c5

Browse files
committed
Add beforeLoad and afterLoad callbacks
1 parent 0df896b commit 4a314c5

File tree

2 files changed

+95
-8
lines changed

2 files changed

+95
-8
lines changed

src/components/LazyLoadImage.jsx

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ class LazyLoadImage extends React.Component {
2323
this.updateVisibility(nextProps.scrollPosition);
2424
}
2525

26-
componentDidUpdate(prevProps, prevState) {
26+
componentDidUpdate() {
2727
if (this.refs.placeholder) {
2828
const boundingBox = {
2929
bottom: this.refs.placeholder.offsetTop +
@@ -43,9 +43,15 @@ class LazyLoadImage extends React.Component {
4343
return;
4444
}
4545

46+
if (!this.isImageInViewport(scrollPosition)) {
47+
return;
48+
}
49+
50+
this.props.beforeLoad();
51+
4652
this.setState({
47-
visible: this.refs.image ? true : this.isImageInViewport(scrollPosition)
48-
});
53+
visible: true
54+
}, this.props.afterLoad);
4955
}
5056

5157
isImageInViewport(scrollPosition) {
@@ -85,7 +91,8 @@ class LazyLoadImage extends React.Component {
8591
}
8692

8793
render() {
88-
const { placeholder, scrollPosition, threshold, ...props } = this.props;
94+
const { afterLoad, beforeLoad, placeholder, scrollPosition, threshold,
95+
...props } = this.props;
8996

9097
if (!this.state.visible) {
9198
return this.getPlaceholder();
@@ -101,6 +108,8 @@ class LazyLoadImage extends React.Component {
101108

102109
LazyLoadImage.propTypes = {
103110
scrollPosition: PropTypes.number.isRequired,
111+
afterLoad: PropTypes.func,
112+
beforeLoad: PropTypes.func,
104113
className: PropTypes.string,
105114
height: PropTypes.number,
106115
placeholder: PropTypes.element,
@@ -109,6 +118,8 @@ LazyLoadImage.propTypes = {
109118
};
110119

111120
LazyLoadImage.defaultProps = {
121+
afterLoad: () => null,
122+
beforeLoad: () => null,
112123
className: '',
113124
height: 0,
114125
placeholder: null,

src/components/LazyLoadImage.spec.js

Lines changed: 80 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,16 @@ const {
1010
} = ReactTestUtils;
1111

1212
describe('LazyLoadImage', function() {
13-
function renderLazyLoadImage(scrollPosition = 0, placeholder = null) {
13+
function renderLazyLoadImage({
14+
afterLoad = () => null,
15+
beforeLoad = () => null,
16+
placeholder = null,
17+
scrollPosition = 0
18+
} = {}) {
1419
return ReactTestUtils.renderIntoDocument(
1520
<LazyLoadImage
21+
afterLoad={afterLoad}
22+
beforeLoad={beforeLoad}
1623
placeholder={placeholder}
1724
scrollPosition={scrollPosition}
1825
src="" />
@@ -32,15 +39,20 @@ describe('LazyLoadImage', function() {
3239
}
3340

3441
it('renders the default placeholder when it\'s not in the viewport', function() {
35-
const lazyLoadImage = renderLazyLoadImage(-1000);
42+
const lazyLoadImage = renderLazyLoadImage({
43+
scrollPosition: -1000
44+
});
3645

3746
expectImages(lazyLoadImage, 0);
3847
expectPlaceholders(lazyLoadImage, 1);
3948
});
4049

4150
it('renders the prop placeholder when it\'s not in the viewport', function() {
4251
const placeholder = <span className="test-placeholder"></span>;
43-
const lazyLoadImage = renderLazyLoadImage(-1000, placeholder);
52+
const lazyLoadImage = renderLazyLoadImage({
53+
scrollPosition: -1000,
54+
placeholder
55+
});
4456

4557
expectImages(lazyLoadImage, 0);
4658
expectPlaceholders(lazyLoadImage, 1, 'test-placeholder');
@@ -54,11 +66,75 @@ describe('LazyLoadImage', function() {
5466
});
5567

5668
it('renders the image when it appears in the viewport', function() {
57-
const lazyLoadImage = renderLazyLoadImage(-1000);
69+
const lazyLoadImage = renderLazyLoadImage({
70+
scrollPosition: -1000
71+
});
5872

5973
lazyLoadImage.componentWillReceiveProps({scrollPosition: 0});
6074

6175
expectImages(lazyLoadImage, 1);
6276
expectPlaceholders(lazyLoadImage, 0);
6377
});
78+
79+
it('doesn\'t trigger beforeLoad when the image is not the viewport', function() {
80+
const beforeLoad = jest.fn();
81+
const lazyLoadImage = renderLazyLoadImage({
82+
beforeLoad,
83+
scrollPosition: -1000
84+
});
85+
86+
expect(beforeLoad).toHaveBeenCalledTimes(0);
87+
});
88+
89+
it('triggers beforeLoad when the image is in the viewport', function() {
90+
const beforeLoad = jest.fn();
91+
const lazyLoadImage = renderLazyLoadImage({
92+
beforeLoad
93+
});
94+
95+
expect(beforeLoad).toHaveBeenCalledTimes(1);
96+
});
97+
98+
it('triggers beforeLoad when the image appears in the viewport', function() {
99+
const beforeLoad = jest.fn();
100+
const lazyLoadImage = renderLazyLoadImage({
101+
beforeLoad,
102+
scrollPosition: -1000
103+
});
104+
105+
lazyLoadImage.componentWillReceiveProps({scrollPosition: 0});
106+
107+
expect(beforeLoad).toHaveBeenCalledTimes(1);
108+
});
109+
110+
it('doesn\'t trigger afterLoad when the image is not the viewport', function() {
111+
const afterLoad = jest.fn();
112+
const lazyLoadImage = renderLazyLoadImage({
113+
afterLoad,
114+
scrollPosition: -1000
115+
});
116+
117+
expect(afterLoad).toHaveBeenCalledTimes(0);
118+
});
119+
120+
it('triggers afterLoad when the image is in the viewport', function() {
121+
const afterLoad = jest.fn();
122+
const lazyLoadImage = renderLazyLoadImage({
123+
afterLoad
124+
});
125+
126+
expect(afterLoad).toHaveBeenCalledTimes(1);
127+
});
128+
129+
it('triggers afterLoad when the image appears in the viewport', function() {
130+
const afterLoad = jest.fn();
131+
const lazyLoadImage = renderLazyLoadImage({
132+
afterLoad,
133+
scrollPosition: -1000
134+
});
135+
136+
lazyLoadImage.componentWillReceiveProps({scrollPosition: 0});
137+
138+
expect(afterLoad).toHaveBeenCalledTimes(1);
139+
});
64140
});

0 commit comments

Comments
 (0)