React技巧之检查元素是否可见

【React技巧之检查元素是否可见】原文链接:https://bobbyhadz.com/blog/react-check-if-element-in-viewport
作者:Borislav Hadzhiev
正文从这开始~
总览 在React中,检查元素是否在视口范围内:

  1. 在元素上设置ref属性。
  2. 使用IntersectionObserver API来跟踪元素是否与视口相交。
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 (Top div {isInViewport1 && '| in viewport ?'}Bottom div {isInViewport2 && '| in viewport ?'}); }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; }

该示例向我们展示了,如何检查元素是否在视口范围内。IntersectionObserver API使我们能够检查一个给定的元素是否与文档相交。
useIsInViewport钩子接收一个指向我们想要追踪的元素的ref对象。
IntersectionObserver IntersectionObserver构造函数接收一个函数,该函数被调用时带有一个entry数组。entry是一个数组,其包含了所有的obeserver的目标元素。这些元素的可见度已经高于或低于intersection observer的比率之一。
每个entry都描述了一个给定元素与根元素(文档)相交的程度。我们解构了这个entry,因为我们的IntersectionObserver只能跟踪一个元素(就是我们设置ref的那个元素)。
我们调用observe()方法,将我们要跟踪的元素传给它 - observer.observe(ref.current)
每当元素进入视口或者存在于视口中时,我们传递给IntersectionObserver()构造函数的函数就会被调用,然后更新state变量。
// ? gets called every time element enters or leaves viewport new IntersectionObserver(([entry]) => setIsIntersecting(entry.isIntersecting), )

如果我们设置ref对象的元素在视口中,useIsInViewport钩子将会返回true。如果元素不在视口中,该钩子将会返回false
需要注意的是,在初始渲染时,useIsInViewport 钩子将会返回false 。因为我们为useState传递的初始值为falseconst [isIntersecting, setIsIntersecting] = useState(false);
如果你想跟踪钩子的返回值的变化,请使用useEffect钩子,并将该值添加到钩子的依赖关系中。
const isInViewport1 = useIsInViewport(ref1); console.log('isInViewport1: ', isInViewport1); useEffect(() => { // ? listen for changes console.log(isInViewport1); }, [isInViewport1]);

    推荐阅读