0

I was wondering if anybody could help.

I've been looking into lots of solutions to check when elements are displayed in the viewpoint and am currently trying to integrate this method into my project - https://www.webtips.dev/webtips/react-hooks/element-in-viewport, this method uses refs however the content I'm wishing to have on the page isn't static but rather mapped. I've found this method to dynamically use refs - https://dev.to/nicm42/react-refs-in-a-loop-1jk4 however I think I'm doing it incorrectly as I'm getting the following error:

TypeError: Failed to execute 'observe' on 'IntersectionObserver': parameter 1 is not of type 'Element'.

Any help at all is most appreciated.

Many thanks, code below.

Component.js

import { useRef, createRef } from 'react'
import useIntersection from './useIntersection.js'

const MyComponent = ({ someStateData }) => {

    const ref= useRef([]);
    ref.current = someStateData.map((title, i) => ref.current[i] ?? createRef());

    const inViewport = useIntersection(ref, '0px');

    if (inViewport) {
        console.log('in viewport:', ref.current);
    }

    {someStateData.map((title, i) => {
        return (
            <div key={title.id} id={title.id} ref={ref.current[i]}>
                {{ title.id }}
            </div>
        )
    })}

}

useIntersection.js

import { useState, useEffect } from 'react'

const useIntersection = (element, rootMargin) => {
    const [isVisible, setState] = useState(false);

    useEffect(() => {
        const observer = new IntersectionObserver(
            ([entry]) => {
                setState(entry.isIntersecting);
            }, { rootMargin }
        );

        element && observer.observe(element);

        return () => observer.unobserve(element);
    }, []);

    return isVisible;
};

export default useIntersection
backtick
  • 2,685
  • 10
  • 18
  • 1
    You might start by looking at the type of value that `useIntersection` expects. It wants an element, but you're giving it an object with a `current` property that is an array of objects with `current` properties. – backtick May 25 '21 at 15:06

1 Answers1

0

ref.current has a collection of refs

const ref= useRef([]);
ref.current = someStateData.map((title, i) => ref.current[i] ?? createRef());

The observe function needs an Element to observe but the code calls with the whole ref

const inViewport = useIntersection(ref, '0px');
const useIntersection = (element, rootMargin) => {
    ...
    ...
observer.observe(element);

quoting @backtick "is an array of objects with current properties", the proper call should be something like

observer.observe(ref.current[i].current)
Fiury
  • 5,540
  • 2
  • 10
  • 9