Last active
March 5, 2023 21:24
-
-
Save gragland/d1175eb983772b077cb17ae0841c5329 to your computer and use it in GitHub Desktop.
React Hook recipe from https://usehooks.com. Demo: https://codesandbox.io/s/y7kr0vll4v
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { useState, useEffect, useRef } from 'react'; | |
// Usage | |
function App() { | |
// Ref for the element that we want to detect whether on screen | |
const ref = useRef(); | |
// Call the hook passing in ref and root margin | |
// In this case it would only be considered onScreen if more ... | |
// ... than 300px of element is visible. | |
const onScreen = useOnScreen(ref, '-300px'); | |
return ( | |
<div> | |
<div style={{ height: '100vh' }}> | |
<h1>Scroll down to next section ๐</h1> | |
</div> | |
<div | |
ref={ref} | |
style={{ | |
height: '100vh', | |
backgroundColor: onScreen ? '#23cebd' : '#efefef' | |
}} | |
> | |
{onScreen ? ( | |
<div> | |
<h1>Hey I'm on the screen</h1> | |
<img src="https://i.giphy.com/media/ASd0Ukj0y3qMM/giphy.gif" /> | |
</div> | |
) : ( | |
<h1>Scroll down 300px from the top of this section ๐</h1> | |
)} | |
</div> | |
</div> | |
); | |
} | |
// Hook | |
function useOnScreen(ref, rootMargin = '0px') { | |
// State and setter for storing whether element is visible | |
const [isIntersecting, setIntersecting] = useState(false); | |
useEffect(() => { | |
const observer = new IntersectionObserver( | |
([entry]) => { | |
// Update our state when observer callback fires | |
setIntersecting(entry.isIntersecting); | |
}, | |
{ | |
rootMargin | |
} | |
); | |
if (ref.current) { | |
observer.observe(ref.current); | |
} | |
return () => { | |
observer.unobserve(ref.current); | |
}; | |
}, []); // Empty array ensures that effect is only run on mount and unmount | |
return isIntersecting; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
observer.unobserve(ref.current);
In the
useEffect
, we should keep a reference to theref.current
like this:const currentRef = ref.current
.Then do:
observer.unobserve(currentRef);
In doing so, we will ensure that
ref.current
doesn't end up changing before this cleanup is run.