Skip to content

Commit 72c397f

Browse files
committed
Use IntersectionObserver when it's available
1 parent 1a638ed commit 72c397f

File tree

5 files changed

+64
-7
lines changed

5 files changed

+64
-7
lines changed

.eslintrc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@
133133
"padded-blocks": [1, "never"],
134134
"quote-props": [1, "as-needed"],
135135
"quotes": [1, 'single'],
136-
"require-jsdoc": 1,
136+
"require-jsdoc": 0,
137137
"semi-spacing": 1,
138138
"semi": 1,
139139
"sort-keys": 0,

src/components/LazyLoadComponent.jsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { PropTypes } from 'prop-types';
33

44
import PlaceholderWithoutTracking from './PlaceholderWithoutTracking.jsx';
55
import PlaceholderWithTracking from './PlaceholderWithTracking.jsx';
6+
import isIntersectionObserverAvailable from '../utils/intersection-observer';
67

78
class LazyLoadComponent extends React.Component {
89
constructor(props) {
@@ -47,7 +48,7 @@ class LazyLoadComponent extends React.Component {
4748
const { className, height, placeholder, scrollPosition, style,
4849
threshold, width } = this.props;
4950

50-
if (this.isScrollTracked) {
51+
if (this.isScrollTracked || isIntersectionObserverAvailable()) {
5152
return (
5253
<PlaceholderWithoutTracking
5354
className={className}

src/components/PlaceholderWithoutTracking.jsx

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,58 @@
11
import React from 'react';
22
import ReactDOM from 'react-dom';
33
import { PropTypes } from 'prop-types';
4+
import isIntersectionObserverAvailable from '../utils/intersection-observer';
45

56
class PlaceholderWithoutTracking extends React.Component {
67
constructor(props) {
78
super(props);
9+
10+
if (!window.LAZY_LOAD_OBSERVER) {
11+
const supportsObserver = isIntersectionObserverAvailable();
12+
13+
window.LAZY_LOAD_OBSERVER = { supportsObserver };
14+
15+
if (supportsObserver) {
16+
const { threshold } = props;
17+
18+
window.LAZY_LOAD_OBSERVER.observer = new IntersectionObserver(
19+
this.checkIntersections, { rootMargin: threshold + 'px' });
20+
}
21+
}
22+
}
23+
24+
checkIntersections(entries) {
25+
entries.forEach(entry => {
26+
if (entry.isIntersecting) {
27+
entry.target.onVisible();
28+
}
29+
});
830
}
931

1032
componentDidMount() {
11-
this.updateVisibility();
33+
if (this.placeholder &&
34+
window.LAZY_LOAD_OBSERVER && window.LAZY_LOAD_OBSERVER.observer) {
35+
this.placeholder.onVisible = this.props.onVisible;
36+
window.LAZY_LOAD_OBSERVER.observer.observe(this.placeholder);
37+
}
38+
39+
if (window.LAZY_LOAD_OBSERVER &&
40+
!window.LAZY_LOAD_OBSERVER.supportsObserver) {
41+
this.updateVisibility();
42+
}
43+
}
44+
45+
componentWillUnMount() {
46+
if (window.LAZY_LOAD_OBSERVER) {
47+
window.LAZY_LOAD_OBSERVER.observer.unobserve(this.placeholder);
48+
}
1249
}
1350

1451
componentDidUpdate() {
15-
this.updateVisibility();
52+
if (window.LAZY_LOAD_OBSERVER &&
53+
!window.LAZY_LOAD_OBSERVER.supportsObserver) {
54+
this.updateVisibility();
55+
}
1656
}
1757

1858
getPlaceholderBoundingBox(scrollPosition = this.props.scrollPosition) {

src/hoc/trackWindowScroll.js

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,17 @@ import React from 'react';
22
import { PropTypes } from 'prop-types';
33
import debounce from 'lodash.debounce';
44
import throttle from 'lodash.throttle';
5+
import isIntersectionObserverAvailable from '../utils/intersection-observer';
56

67
const trackWindowScroll = (BaseComponent) => {
78
class ScrollAwareComponent extends React.Component {
89
constructor(props) {
910
super(props);
1011

12+
if (isIntersectionObserverAvailable()) {
13+
return;
14+
}
15+
1116
const onChangeScroll = this.onChangeScroll.bind(this);
1217

1318
if (props.delayMethod === 'debounce') {
@@ -31,22 +36,25 @@ const trackWindowScroll = (BaseComponent) => {
3136
}
3237

3338
componentDidMount() {
34-
if (typeof window == 'undefined') {
39+
if (typeof window == 'undefined' || isIntersectionObserverAvailable()) {
3540
return;
3641
}
3742
window.addEventListener('scroll', this.delayedScroll);
3843
window.addEventListener('resize', this.delayedScroll);
3944
}
4045

4146
componentWillUnmount() {
42-
if (typeof window === 'undefined') {
47+
if (typeof window == 'undefined' || isIntersectionObserverAvailable()) {
4348
return;
4449
}
4550
window.removeEventListener('scroll', this.delayedScroll);
4651
window.removeEventListener('resize', this.delayedScroll);
4752
}
4853

4954
onChangeScroll() {
55+
if (isIntersectionObserverAvailable()) {
56+
return;
57+
}
5058
this.setState({
5159
scrollPosition: {
5260
x: (typeof window == 'undefined' ?
@@ -63,10 +71,12 @@ const trackWindowScroll = (BaseComponent) => {
6371

6472
render() {
6573
const { delayMethod, delayTime, ...props } = this.props;
74+
const scrollPosition = isIntersectionObserverAvailable() ?
75+
null : this.state.scrollPosition;
6676

6777
return (
6878
<BaseComponent
69-
scrollPosition={this.state.scrollPosition}
79+
scrollPosition={scrollPosition}
7080
{...props} />
7181
);
7282
}

src/utils/intersection-observer.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
export default function() {
2+
return (
3+
'IntersectionObserver' in window &&
4+
'isIntersecting' in window.IntersectionObserverEntry.prototype
5+
);
6+
}

0 commit comments

Comments
 (0)