import React, { FC, useEffect, useMemo, useRef, useState } from 'react'; import { ScrollView, vevet } from 'vevet'; import { isUndefined, useDeepCompareMemoize } from '@anton.bobrov/react-hooks'; import { IScrollViewContext, ScrollViewContext } from './utils/context'; import { IScrollViewProviderProps } from './types'; /** * ScrollView provider. * ScrollView lets you detect visible elements in viewport */ export const Provider: FC = ({ children, instanceKey, intersectionRoot = null, states = 'in', hasDelay = true, maxDelay = 1000, direction = 'vertical', viewportTarget, resizeDebounce = 0, isEnabled = false, ...props }) => { const [scrollView, setScrollView] = useState(); const vevetRef = useRef(vevet); const changeableProps = { ...props, isEnabled }; const initialChangeablePropsRef = useRef(changeableProps); useEffect(() => { if (!vevetRef.current || isUndefined(instanceKey)) { return undefined; } const instance = new ScrollView({ ...initialChangeablePropsRef.current, intersectionRoot, states, hasDelay, maxDelay, direction, viewportTarget: viewportTarget || (vevet.isMobile ? 'width' : 'any'), resizeDebounce, }); setScrollView(instance); return () => { setScrollView(undefined); instance.destroy(); }; }, [ instanceKey, direction, hasDelay, intersectionRoot, maxDelay, resizeDebounce, states, viewportTarget, ]); const contextValue: IScrollViewContext = useMemo( () => ({ scrollView }), [scrollView], ); useEffect(() => { if (!scrollView) { return; } scrollView.changeProps(changeableProps); // eslint-disable-next-line react-hooks/exhaustive-deps }, [scrollView, useDeepCompareMemoize(changeableProps)]); return ( {children} ); };