How to Check if An Element is in the Viewport with React Hooks

How to Check if An Element is in the Viewport with React Hooks

Ferenc Almasi β€’ Last updated 2021 July 13 β€’ Read time 3 min read
  • twitter
  • facebook
React

As a frontend developer, you commonly come across requests such as lazy loading images, triggering animations on elements entering into the screen, or sending tracking to see if a user has seen a section of your page. For such cases, you can use the following custom React hook that uses the combination of useState, useEffect, and the IntersectionObserver API internally:

Copied to clipboard! Playground
import { useState, useEffect } from 'react'

const useIntersection = (element, rootMargin) => {
    const [isVisible, setState] = useState(false);

    useEffect(() => {
        const observer = new IntersectionObserver(
            ([entry]) => {
                setState(entry.isIntersecting);
            }, { rootMargin }
        );

        element.current && observer.observe(element.current);

        return () => observer.unobserve(element.current);
    }, []);

    return isVisible;
};
useIntersection.js

With the return statement in the useEffect, you can remove the observer once your component is unmounted. This ensures that you are not listening to intersection events for elements that are not even on the page.

Also with this hook, you can also specify when to trigger the state change: if only 1px of the element is visible, or if the whole block is on the screen. You can use it in your components like so:

Copied to clipboard! Playground
import React, { useRef } from 'react';
import useIntersection from './useIntersection'

const App = () => {
    const ref = useRef();
    const inViewport = useIntersection(ref, '0px'); // Trigger as soon as the element becomes visible
    const inViewport = useIntersection(ref, '-200px'); // Trigger if 200px is visible from the element

    if (inViewport) {
        console.log('in viewport:', ref.current);
    }

    return (
        <React.Fragment>
            <header />
            <main />
            <footer ref={ref} />
        </React.Fragment>
    );
}
useIntersection.js

This will log to the console, every time the element becomes visible. If you only want your hooks to be fired once, you can add an if statement into your observer, that will ensure it will fire only once, and never again.

Copied to clipboard! Playground
const observer = new IntersectionObserver(
    ([entry]) => {
        if (entry.isIntersecting) {
            setState(entry.isIntersecting);
            observer.unobserve(element.current);
        }
    }, { rootMargin }
);
useIntersection.js

If you would like to see it in action, give it a try on Codesandbox

Try the hook on codesandbox
How to Check if An Element is in the Viewport with React Hooks
If you would like to see more Webtips, follow @flowforfrank

If you are interested in reading more about React hooks, see more examples for custom hooks or just learn about the basics, make sure to check out the article below.

All You Need to Know About React Hooks
  • twitter
  • facebook
React
Did you find this page helpful?
πŸ“š More Webtips
Frontend Course Dashboard
Master the Art of Frontend
  • check Access 100+ interactive lessons
  • check Unlimited access to hundreds of tutorials
  • check Prepare for technical interviews
Become a Pro

Courses

Recommended

This site uses cookies We use cookies to understand visitors and create a better experience for you. By clicking on "Accept", you accept its use. To find out more, please see our privacy policy.