Track React component in viewport using Intersection Observer API
npm install react-in-viewport
Library to detect whether or not a component is in the viewport, using the Intersection Observer API.
This library also uses MutationObserver to detect the change of the target element.
``npm install --save react-in-viewport`
`yarn add react-in-viewport`
A common use case is to load an image when a component is in the viewport (lazy load).
We have traditionally needed to monitor scroll position and calculate the viewport size, which can be a scroll performance bottleneck.
Modern browsers now provide a new API--Intersection Observer API--which can make implementating this effort much easier and performant.
For browsers not supporting the API, you will need to load a polyfill.
Browser support table
`js`
require('intersection-observer');
The core logic is written using React Hooks. We provide two interfaces: you can use handleViewport, a higher order component (HOC) for class based components, or use hooks directly, for functional components.
The HOC acts as a wrapper and attaches the intersection observer to your target component. The HOC will then pass down extra props, indicating viewport information and executing a callback function when the component enters and leaves the viewport.
HOC, you will receive inViewport props indicating whether the component is in the viewport or not.handleViewport HOC accepts three params: handleViewport(Component, Options, Config)| Params | Type | Description |
|-----------|---------------|------------------------------------------------------------------------------------------------------------------------------------|
| Component | React Element | Callback function for when the component enters the viewport |
| Options | Object | Options you want to pass to Intersection Observer API | |
| Config | Object | Configs for HOC (see below) |
$3
| Params | Type | Default | Description |
|-------------------|---------|------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------|
| disconnectOnLeave | boolean | false | Disconnect intersection observer after leave |
$3
| Props | Type | Default | Description |
|-----------------|----------|---------|-------------------------------------------------|
| onEnterViewport | function | | Callback function for when the component enters the viewport |
| onLeaveViewport | function | | Callback function for when the component leaves the viewport |
The HOC preserves
onEnterViewport and onLeaveViewport props as a callback
$3
| Props | Type | Default | Description |
|------------|-----------|---------|-----------------------------------------------------------------------------------|
| inViewport | boolean | false | Whether your component is in the viewport |
| forwardedRef | React ref | | Assign this prop as a ref on your component |
| enterCount | number | | Numbers of times your component has entered the viewport |
| leaveCount | number | | Number of times your component has left the viewport |
_NOTE_: Need to add
ref={this.props.forwardedRef} to your component#### Example of a functional component
`tsx
import handleViewport, { type InjectedViewportProps } from 'react-in-viewport';const Block = (props: InjectedViewportProps) => {
const { inViewport, forwardedRef } = props;
const color = inViewport ? '#217ac0' : '#ff9800';
const text = inViewport ? 'In viewport' : 'Not in viewport';
return (
{ text }
);
};
const ViewportBlock = handleViewport(Block, / options: {}, config: {} /);
const Component = (props) => (
Scroll down to make component in viewport
console.log('enter')} onLeaveViewport={() => console.log('leave')} />
))
`#### Example for enter/leave counts
- If you need to know how many times the component has entered the viewport, use the prop
enterCount.
- If you need to know how many times the component has left the viewport, use the prop leaveCount.`javascript
import React, { Component } from 'react';
import handleViewport from 'react-in-viewport';class MySectionBlock extends Component {
getStyle() {
const { inViewport, enterCount } = this.props;
//Fade in only the first time we enter the viewport
if (inViewport && enterCount === 1) {
return { WebkitTransition: 'opacity 0.75s ease-in-out' };
} else if (!inViewport && enterCount < 1) {
return { WebkitTransition: 'none', opacity: '0' };
} else {
return {};
}
}
render() {
const { enterCount, leaveCount, forwardedRef } = this.props;
return (
Hello
{Enter viewport: ${enterCount} times}
{Leave viewport: ${leaveCount} times}
);
}
}
const MySection = handleViewport(MySectionBlock, { rootMargin: '-1.0px' });
export default MySection;
`$3
Alternatively, you can also directly using
useInViewport hook which takes similar configuration as HOC.`js
import React, { useRef } from 'react';
import { useInViewport } from 'react-in-viewport';const MySectionBlock = () => {
const myRef = useRef(null);
const {
inViewport,
enterCount,
leaveCount,
} = useInViewport(
myRef,
options,
config = { disconnectOnLeave: false },
props
);
return (
Hello
{Enter viewport: ${enterCount} times}
{Leave viewport: ${leaveCount} times}
);
};
``- Tinder