当 none 个元素可见时,IntersectionObserverAPI Return 为默认状态

IntersectionObserverAPI Return to default state when none of the elements are visible

我正在使用 React Hook 来检测元素何时在视口中可见。在那之前,一切正常,但我需要 'reset' 隐藏所有内容时的状态(比如到达页脚或页眉)。

这是我的钩子:

import { useState, useEffect, useRef } from 'react'

const useIntersect = (ref) => {
  const [isOnScreen, setIsOnScreen] = useState(false)
  const observerRef = useRef(null)

  useEffect(() => {
    observerRef.current = new IntersectionObserver(([entry]) => {
      setIsOnScreen(entry.isIntersecting)
    })
  }, [])

  useEffect(() => {
    observerRef.current.observe(ref.current)
    return () => observerRef.current.disconnect()
  }, [ref])

  return isOnScreen
}

export default useIntersect

这是我正在更新的状态:

  const elementRef = useRef(null)
  const[state, setState] = useState('nothing is visible')
  const onScreen = useIntersect(elementRef)

  useEffect(() => {
    return onScreen ? setState('an item is visible') : null
  })

  return (
    <Item ref={elementRef}>
      ...
    </Item>
  )

当所有元素都离开视口时(当不满足 onScreen 条件时),我需要能够对某些东西(比如字符串)说 setState('...'),但即使我到达页脚时什么都不可见,它保留内存中的最后一项。

我尝试了很多方法,但我想不出出路:(

感谢您的帮助!

我认为问题在于您如何将 elementRef 传递给挂钩。

useIntersect useEffect 不会在 elementRef 改变时执行。

import { useState, useEffect, useRef } from "react";

const useIntersect = () => {
  const ref = useRef(null);
  const [isOnScreen, setIsOnScreen] = useState(false);

  useEffect(() => {
    if (!ref) {
      const observer = new IntersectionObserver(([entry]) =>
        setIsOnScreen(entry.isIntersecting)
      );
      observer.observe(ref.current);
      return () => observer.disconnect();
    }
  }, [ref]);

  return [isOnScreen, ref];
};

export default useIntersect;

// -----------------------------Component-------------------------------
const [state, setState] = useState("nothing is visible");
const [onScreen, elementRef] = useIntersect();

useEffect(() => {
  return onScreen ? setState("an item is visible") : null;
});

return <Item ref={elementRef}></Item>;

你的钩子实现看起来不错。您可能需要重新检查 Item 组件的高度。 检查此代码沙箱与您的挂钩实现是否正常工作 : https://codesandbox.io/s/elegant-wood-ruks2?file=/src/App.js

我相信你的 useIntersect 钩子应该为第二个 useEffect

添加对 ref.current 而不是 ref 的依赖

所以

useEffect(() => {
  observerRef.current.observe(ref.current)
  return () => observerRef.current.disconnect()
}, [ref.current]);

然后在组件中使用时做

useEffect(() => {
  return onScreen ? setState('an item is visible') : setState('nothing is visible');
}, [onScreen])

你应该添加对 onScreen 的依赖,这样它只会在 onScreen 发生变化时更新,最后你应该为 onScreen 的场景调用 setState ] 与您想要的值不符。