Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Gatsby - IntersectionObserver is not defined

I am trying to build my gatsby project but I am unable due to the IntersectionObserver not being recognized. I use the intersectionObserver inside an InView component:

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


const InView = ({ children }) => {
    const [boundingClientY, setBoundingClientY] = useState(null)
    const [direction, setDirection] = useState(null)
    const [element, setElement] = useState(null)
    const [inView, setInView] = useState(false)



    const observer = useRef(new IntersectionObserver((entries) => {
        const first = entries[0]
        const { boundingClientRect } = first
        first.isIntersecting && setInView(true)
        !first.isIntersecting && setInView(false)
        boundingClientRect.y > boundingClientY && setDirection('down')
        boundingClientRect.y < boundingClientY && setDirection('up')
        boundingClientY && setBoundingClientY(first.boundingClientRect.y)

    }))


    useEffect(() => {
        const currentElement = element
        const currentObserver = observer.current
        currentElement && currentObserver.observe(currentElement)
        // console.log(currentObserver)
        return () => {
            currentElement && currentObserver.unobserve(currentElement)
        };
    }, [element])

    const styles = {
        opacity: inView ? 1 : 0,
        transform: `
            translateY(${!inView ?
                direction === 'up' ? '-20px' : '20px'
                : 0})
            rotateY(${!inView ? '35deg' : 0})
            scale(${inView ? 1 : 0.9})
            `,
        transition: 'all 0.4s ease-out 0.2s'
    }

    return (
        <div ref={setElement} style={styles}>

            {children}

        </div>
    )
}

export default InView

I have a wrapper for the root element to enable a global state and have tried importing the polyfill inside gatsby-browser.js:

import React from 'react'
import GlobalContextProvider from './src/components/context/globalContextProvider'

export const wrapRootElement = ({ element }) => {
    return (
        <GlobalContextProvider>
            {element}
        </GlobalContextProvider>
    )
}

export const onClientEntry = async () => {
    if (typeof IntersectionObserver === `undefined`) {
        await import(`intersection-observer`);
    }
}
like image 955
Aiden Barrett Avatar asked Dec 20 '19 11:12

Aiden Barrett


People also ask

What is Intersectionobserver in react?

The Intersection Observer API lets code register a callback function that is executed whenever an element they wish to monitor enters or exits another element (or the viewport), or when the amount by which the two intersect changes by a requested amount.

What is useInView?

A simple state hook for when an element is within the viewport. useInView is a tiny (0.6kb) hook that detects when the provided element is within the viewport. function Component() { const ref = useRef(null)


1 Answers

This is an error on build, right ($ gatsby build)? If that's the case this has nothing to do with browser support.

It is the fact that IntersectionObserver is a browser API and you should not use browser APIs during server side rendering. Instead you try to utilize them after components have mounted. To solve this initialize your observer in useEffect() instead of useRef() as you currently do.

...
const observer = useRef();

useEffect(() => {
  observer.current = new IntersectionObserver({ ... });
}, []); // do this only once, on mount
...
like image 166
Z. Zlatev Avatar answered Oct 07 '22 01:10

Z. Zlatev