UNPKG

@state-less/leap-frontend

Version:

A collection of open source fullstack services powered by React Server

60 lines (59 loc) 1.86 kB
import { useEffect, useRef, useState } from 'react'; export const useSyncedState = (defValue, updateFn, { draft, successFn, } = { draft: false, }) => { const timeout = useRef(null); const timestampSave = useRef(0); const timestampLocal = useRef(0); const [localValue, setLocalValue] = useState(defValue); const [loading, setLoading] = useState(false); const setValue = async (value) => { setLocalValue(value); timestampLocal.current = +new Date(); if (timeout.current) clearTimeout(timeout.current); const save = async () => { setLoading(true); timestampSave.current = +new Date(); await updateFn(value); successFn?.(value); }; if (draft) { await save(); } else { timeout.current = setTimeout(async () => { await save(); }, 1500); } }; useEffect(() => { if (timestampLocal <= timestampSave) { setLocalValue(defValue); } setLoading(false); }, [defValue]); return [localValue, setValue, { loading }]; }; export const useIsOffScreen = () => { const [isOffScreen, setIsOffScreen] = useState(false); const ref = useRef(null); useEffect(() => { if (!ref?.current) return; const obs = new IntersectionObserver((entries) => { if (entries[0]?.isIntersecting) { setIsOffScreen(true); } else if (entries[0]?.boundingClientRect?.y > 0) { setIsOffScreen(false); } }, { root: document.body, rootMargin: '0px 0px -100%', threshold: 0.0, }); obs.observe(ref?.current); }, [setIsOffScreen]); return [ref, isOffScreen]; };