import React , { useCallback , useEffect , useMemo , useRef } from "react" ; export type IntersectionCallback = ( entry : IntersectionObserverEntry ) => void ; export type Observe = ( target : Element , callback : IntersectionCallback ) => ( ) => void ; export interface IntersectionContext { observe : Observe ; } const IntersectionContext = React . createContext < IntersectionContext > ( { } as any ) ; export const useIntersectionContext = ( ) => React . useContext ( IntersectionContext ) ; export const IntersectionProvider = ( { children } ) => { const callbacks = useRef ( new Map < Element , IntersectionCallback > ( ) ) ; const onIntersect = useCallback ( ( entries ) => entries . forEach ( ( entry ) => { const callback = callbacks . current . get ( entry . target ) ; if ( ! callback ) { return ; } callback ( entry ) ; } ) , [ ] ) ; const observer = useMemo ( ( ) => new IntersectionObserver ( onIntersect , { rootMargin : "0px" , threshold : 0.25 , } ) , [ onIntersect ] ) ; useEffect ( ( ) => ( ) => observer . disconnect ( ) , [ observer ] ) ; const observe = useCallback ( ( element , callback ) => { callbacks . current . set ( element , callback ) ; observer . observe ( element ) ; return ( ) => { observer . unobserve ( element ) ; callbacks . current . delete ( element ) ; } ; } , [ observer ] ) ; return ( < IntersectionContext . Provider value = { { observe } } > { children } < /IntersectionContext.Provider>); } ;