【问题标题】:IntersectionObserver not updating in ReactIntersectionObserver 未在 React 中更新
【发布时间】:2021-12-23 18:53:32
【问题描述】:

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

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 不同(更好)的方法?

【问题讨论】:

    标签: reactjs intersection-observer


    【解决方案1】:

    这与 IntersectionObserveruseEffect 挂钩中实例化时未完全加载的 DOM 内容有关。

    不使用window.onscroll 的一种解决方法是在组件中运行钩子并将您的设置器作为道具传递。

    类似的东西

    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); } } />
      </>;
    }
    

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

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

    【讨论】:

    • 这是一个很好的解决方案,并且有效。我想知道这是否比 window.onscroll 消耗更多或更少的资源
    • @soffyo _ 以您已实现的方式使用 window.onscroll,每次更改对话框的 DOM 元素的状态时都会创建一个新的 IntersectionObserver。以我表达的方式,它只创建一次,不会重新渲染。它也不是有条件地呈现的。就哪个性能更高而言,我认为我们可能正在讨论在 UX 方面可以忽略不计的性能。我不知道渲染 null 渲染的 React 组件需要多少时间,但我认为创建事件侦听器不会太多。这是我自己的看法。由您决定。
    猜你喜欢
    • 2018-12-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-29
    • 1970-01-01
    • 1970-01-01
    • 2015-06-11
    相关资源
    最近更新 更多