IntersectionObserver 没有在 React 中更新

IntersectionObserver not updating in React

以下代码将在元素通过滚动进入或离开视口时立即触发状态更改

const dialog = useRef(),
[visible, set] = useState(false)

useEffect(() => {
        const observer = new IntersectionObserver((e) => {
            set(e[0].isIntersecting ? true : false)
        }, {root: null, rootMargin: '0px', threshold: 0})
        observer.observe(dialog.current)
        return () => observer.disconnect()
    }, [dialog.current])

return <div ref={dialog}>my dialog</div>

但如果我尝试这样的事情

const observer = new IntersectionObserver((e) => {
            set(e[0].boundingClientRect.y <= 0 ? true : false)
        }, {root: null, rootMargin: '0px', threshold: 0})

仅当触发重新渲染时状态才会更新,而我希望它在我滚动视口时根据观察到的元素的 boundingClientRect.y 值触发。 我发现完成这项工作的唯一方法是在 useEffect 中使用 window.onscroll 事件并将观察者放在其中,但它对我来说不太好。有没有比使用 window.onscroll 不同(更好)的方法?

这是因为在 useEffect 挂钩中实例化 IntersectionObserver 时 DOM 内容未完全加载。

不使用 window.onscroll 的解决方法是 运行 组件中的钩子并将你的 setter 作为道具传递。

像这样

function MyObserver({ selector, callback }){
  useEffect(() => {
    const observer = new IntersectionObserver(
      (entries) => callback(entries),
      { root: null, rootMargin: '0px', threshold: 0 });

    const element = document.querySelector(selector);

    observer.observe(element);

    return () => {
      observer.disconnect();
    };
      
  }, []);


  return null;
}

function Main() {
  [visible, set] = useState(false);

  return <>
    <div className="myDialog">my dialog</div>
    <MyObserver selector=".myDialog"
      callback={ (e) => { set(e[0].isIntersecting ? true : false); } } />
  </>;
}

现在观察者逻辑是渲染流的一部分,发生在对话框之后,因此它应该正确更新。

当我遇到这个确切的问题时,这对我有用。