20 December 2021
Intersection Observer React Hook
I was building a page in React recently and wanted to have a component animate upon scrolling into view. I knew IntersectionObserver was the right tool for the job and decided to take a fun digression to write my own React hook.
Here’s the result:
The onIntersect
parameter is used in the deps
of the useEffect
call, so you’ll want to make sure you’re either using a function that’s defined outside the component or safely created through useCallback in order to maintain referential equality across render calls.
A simple example would be:
import React from 'react';
const onObserveSetAnimate = (elt: HTMLElement) => elt.classList.add('animate');
const Foo = () => {
const ref = useIntersectionObserver(onObserveSetAnimate);
return <div ref={ref}>hello, world</div>;
}
I like how small and self-contained hooks can be, and writing them usually feels like a fun little puzzle that results in a new, reusable tool for my codebase, however, you can usually save time just seeing what other people have already done. Upon writing this, I did a quick search and immediately found existing examples online, such as this one from usehooks-ts.com.
Their code inspired me to add a couple updates to my script:
- I added the destructuring assignment for the
IntersectionObserverInit
args param. For TypeScript, you need to assign it to a default variable in order to make it optional (line 19). - I employed
JSON.stringify(threshold)
in theuseEffect
to ensure referential equality in the case that it’s an Array that’s generated uniquely each render.
It was also interesting to see the different approach where their example takes a ref
and mine instead takes a callback and returns a ref
. My approach felt straightforward for my particular application, however their approach seems more declarative. I’d love to hear thoughts on differences between the two! Regardless, one beauty of open source is learning from how different people solve similar problems.