首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >带有React & Hooks的IntersectionObserver

带有React & Hooks的IntersectionObserver
EN

Stack Overflow用户
提问于 2019-10-11 20:58:45
回答 4查看 10.4K关注 0票数 4

我正在尝试使用React/Hooks和交叉点观察者API来跟踪元素可见性。但是,我不知道如何使用"useEffect“设置观察值。有人知道我是怎么做到的吗?我的解决方案不起作用..。

代码语言:javascript
复制
function MainProvider({ children }) {
  const [targetToObserve, setTargetToObserve] = useState([]);

  window.addEventListener("load", () => {
    const findTarget = document.querySelector("#thirdItem");
    setTargetToObserve([findTarget]);
  });

  useEffect(() => {
    const observer = new IntersectionObserver(
      ([entry]) => {
        if (entry.intersectionRatio === 0.1) {
          console.log("It works!");
        }
      },
      {
        root: null,
        rootMargin: "0px",
        threshold: 0.1
      }
    );
    if (targetToObserve.current) {
      observer.observe(targetToObserve.current);
    }
  }, []);

  return (
    <main>
     <div className="Section-item" id="firstItem"></div>
     <div className="Section-item" id="secondItem"></div>
     <div className="Section-item" id="thirdItem"></div>
    </main>
  );
}
EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2019-10-14 18:04:05

需要使用React.useRef()而不是addEventListener('load',function() ),因为eventListener会在某些东西出现在屏幕上之前运行。

代码语言:javascript
复制
import React, { useRef, useEffect } from 'react'

function MainProvider({ children }) {
  const ref = useRef();

  useEffect(() => {
    const observer = new IntersectionObserver(
      ([entry]) => {
        console.log(entry);

        if (entry.isIntersecting) {
          //do your actions here
          console.log('It works!')
        }
      },
      {
        root: null,
        rootMargin: "0px",
        threshold: 0.1
      }
    );
    if (ref.current) {
      observer.observe(ref.current);
    }
  }, [ref]);

  return (
    <main>
     <div className="Section-item" id="firstItem"></div>
     <div className="Section-item" ref={ref} id="secondItem"></div>
     <div className="Section-item" id="thirdItem"></div>
    </main>
  );
}
票数 8
EN

Stack Overflow用户

发布于 2020-11-18 19:59:04

这是一个可重用的钩子,它使用refuseEffect清理功能来防止在挂载/卸载大量组件时发生内存泄漏

钩子

代码语言:javascript
复制
function useOnScreen(ref) {

  const [isIntersecting, setIntersecting] = useState(false)

  const observer = new IntersectionObserver(
    ([entry]) => setIntersecting(entry.isIntersecting)
  )

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

  return isIntersecting
}

组件中的用法

代码语言:javascript
复制
function DumbComponent() {

  const ref = useRef()

  const onScreen = useOnScreen(ref)

  return <div ref={ref}>{onScreen && "I'm on screen!"}</div>
}
票数 9
EN

Stack Overflow用户

发布于 2021-06-04 01:27:10

JavaScript

钩子

代码语言:javascript
复制
import { useEffect, useState, useRef } from 'react';

export function useOnScreen(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;
}

用法:

代码语言:javascript
复制
import { useRef } from 'react';
import useOnScreen from './useOnScreen';

function MyComponent() {
  const elementRef = useRef(null);
  const isOnScreen = useOnScreen(elementRef);

  console.log({isOnScreen});

  return (
    <div>
      <div style={{ paddingBottom: '140vh' }}>scroll to element...</div>
      <div ref={elementRef}>my element</div>
    </div>
  );
}

TypeScript

钩子

代码语言:javascript
复制
import { useEffect, useState, useRef, RefObject } from 'react';

export default function useOnScreen(ref: RefObject<HTMLElement>) {
  const observerRef = useRef<IntersectionObserver | null>(null);
  const [isOnScreen, setIsOnScreen] = useState(false);

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

  useEffect(() => {
    observerRef.current.observe(ref.current);

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

  return isOnScreen;
}

用法:

代码语言:javascript
复制
import { useRef } from 'react';
import useOnScreen from './useOnScreen';

function MyComponent() {
  const elementRef = useRef<HTMLDivElement>(null);
  const isOnScreen = useOnScreen(elementRef);

  console.log({isOnScreen});

  return (
    <div>
      <div style={{ paddingBottom: '140vh' }}>scroll to element...</div>
      <div ref={elementRef}>my element</div>
    </div>
  );
}

https://codesandbox.io/s/useonscreen-uodb1?file=/src/useOnScreen.ts

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/58341787

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档