Original link: https://bobbyhadz.com/blog/react-check-if-element-in-viewport
Author: Borislav Hadzhiev
The text starts here~
Overview
In React, check if an element is within viewport bounds:
- Set the
ref
attribute on the element. - Use the
IntersectionObserver
API to track whether an element intersects the viewport.
import {useEffect, useRef, useState, useMemo} from 'react';
export default function App() {
const ref1 = useRef(null);
const ref2 = useRef(null);
const isInViewport1 = useIsInViewport(ref1);
console.log('isInViewport1: ', isInViewport1);
const isInViewport2 = useIsInViewport(ref2);
console.log('isInViewport2: ', isInViewport2);
return (
<div>
<div ref={ref1}>Top div {isInViewport1 && '| in viewport ✅'}</div>
<div style={{height: '155rem'}} />
<div ref={ref2}>Bottom div {isInViewport2 && '| in viewport ✅'}</div>
</div>
);
}
function useIsInViewport(ref) {
const [isIntersecting, setIsIntersecting] = useState(false);
const observer = useMemo(
() =>
new IntersectionObserver(([entry]) =>
setIsIntersecting(entry.isIntersecting),
),
[],
);
useEffect(() => {
observer.observe(ref.current);
return () => {
observer.disconnect();
};
}, [ref, observer]);
return isIntersecting;
}
This example shows us how to check if an element is within the viewport. IntersectionObserver
API enables us to check if a given element intersects the document.
useIsInViewport
hook receives aref
object pointing to the element we want to track.
IntersectionObserver
IntersectionObserver
The constructor receives a function, which is called with an array of entry
. entry
is an array that contains all the target elements of obeserver
. The visibility of these elements is already above or below one of the ratios intersection observer
.
Each entry
describes how much a given element intersects the root element (document). We deconstructed this entry
because our IntersectionObserver
can only track one element (the one we set ref
).
We call the observe()
method, passing it the element we want to track observer.observe(ref.current)
.
Whenever an element enters or exists in the viewport, the function we pass to the IntersectionObserver()
constructor is called, which then updates the state
variable.
// 👇️ gets called every time element enters or leaves viewport
new IntersectionObserver(([entry]) =>
setIsIntersecting(entry.isIntersecting),
)
If we set the ref
object's element in the viewport, the useIsInViewport
hook will return true
. If the element is not in the viewport, the hook will return false
.
Note that on initial render, the useIsInViewport
hook will return false
. Because we passed the initial value for useState
false
. const [isIntersecting, setIsIntersecting] = useState(false);
If you want to track changes in the return value of a hook, use the useEffect
hook and add the value to the hook's dependencies.
const isInViewport1 = useIsInViewport(ref1);
console.log('isInViewport1: ', isInViewport1);
useEffect(() => {
// 👇️ listen for changes
console.log(isInViewport1);
}, [isInViewport1]);
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。