DEV Community

Cover image for React Custom Hook: useOnScreen
Sergey Leschev
Sergey Leschev

Posted on

React Custom Hook: useOnScreen

In this article series, we embark on a journey through the realm of custom React hooks, discovering their immense potential for elevating your development projects. Our focus today is on the "useOnScreen" hook, one of the many carefully crafted hooks available in the collection of React custom hooks.

Github: https://github.com/sergeyleschev/react-custom-hooks

import { useEffect, useState } from "react"

export default function useOnScreen(ref, rootMargin = "0px") {
    const [isVisible, setIsVisible] = useState(false)
    useEffect(() => {
        if (ref.current == null) return
        const observer = new IntersectionObserver(
            ([entry]) => setIsVisible(entry.isIntersecting),
            { rootMargin }
        )
        observer.observe(ref.current)
        return () => {
            if (ref.current == null) return
            observer.unobserve(ref.current)
        }
    }, [ref.current, rootMargin])
    return isVisible
}
Enter fullscreen mode Exit fullscreen mode

The useOnScreen hook leverages the power of the Intersection Observer API, making it efficient and reliable. By simply providing a ref to the element you want to monitor, useOnScreen will notify you when it enters or exits the viewport.

One of the key advantages of useOnScreen is its simplicity. With just a few lines of code, you can detect if an element is visible and respond accordingly. This can be immensely useful in scenarios where you want to trigger animations, lazy load images, or load additional content as the user scrolls.

To use this hook, first import it into your component file. Then, create a ref using the useRef hook to target the desired element. Pass the ref as the first argument to the useOnScreen hook, and you're all set! You can also provide an optional rootMargin value to adjust the visible threshold.

import { useRef } from "react"
import useOnScreen from "./useOnScreen"

export default function OnScreenComponentComponent() {
    const headerTwoRef = useRef()
    const visible = useOnScreen(headerTwoRef, "-100px")
    return (
        <div>
            <h1>Header</h1>
            <div>
              ...
            </div>
            <h1 ref={headerTwoRef}>Header 2 {visible && "(Visible)"}</h1>
            <div>
              ...
            </div>
        </div>
    )
}
Enter fullscreen mode Exit fullscreen mode

In our example code, the OnScreenComponentComponent demonstrates how to use the useOnScreen hook. By attaching the ref to the second header element, we can display a "(Visible)" text when it enters the viewport. Feel free to customize the logic within your component to suit your specific needs.

Full Version | React Custom Hooks:
https://dev.to/sergeyleschev/supercharge-your-react-projects-with-custom-hooks-pl4

Top comments (3)

Collapse
 
oculus42 profile image
Samuel Rouse

This is great! The IntersectionObserver is a really useful system, especially to cut down on expensive computation. Your use of rootMargin provides a nice, simple way to adjust the "point" at which visible becomes true.

Have you considered version of the hook accepting a callback like the IntersectionObserver does to give even greater flexibility?

Collapse
 
sergeyleschev profile image
Sergey Leschev

Introducing callbacks could make the hook more complex to use.

Collapse
 
sergeyleschev profile image
Sergey Leschev

Thank you, Samuel! I'm glad you found the article helpful.