An open API service indexing awesome lists of open source software.

https://github.com/roderickhsiao/react-in-viewport

Detect if React component is in viewport
https://github.com/roderickhsiao/react-in-viewport

intersection-observer lazyload react viewport

Last synced: about 1 year ago
JSON representation

Detect if React component is in viewport

Awesome Lists containing this project

README

          


React In Viewport


npm
gzip size
downloads


Library to detect whether or not a component is in the viewport, using the [Intersection Observer API](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API).

This library also uses [MutationObserver](https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver) to detect the change of the target element.

```npm install --save react-in-viewport```

```yarn add react-in-viewport```

## Examples

[Demo](https://roderickhsiao.github.io/react-in-viewport/)

## Why

A common use case is to load an image when a component is in the viewport ([lazy load](https://medium.com/@roderickhsiao/performance-101-i-know-how-to-load-images-a262d556250f)).

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](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API)--which can make implementating this effort much easier and performant.

## Polyfill

For browsers not supporting the API, you will need to load a [polyfill](https://www.npmjs.com/package/intersection-observer).
[Browser support table](https://caniuse.com/#feat=intersectionobserver)

```js
require('intersection-observer');
```

## Design

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.

## Usages

### Using Higher Order Component
When wrapping your component with `handleViewport` 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](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API) | |
| Config | Object | Configs for HOC (see below) |

### Supported config

| Params | Type | Default | Description |
|-------------------|---------|------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------|
| disconnectOnLeave | boolean | false | Disconnect intersection observer after leave |

### HOC Component Props

| 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

### Props passed down by HOC to your component

| 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;
```

### Using Hooks

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`}




);
};
```

## Who is using this component

- [Tinder](https://tinder.com)