import { useEffect, useMemo, useRef, useState } from 'react'; import { AxiosPromise, AxiosResponse } from 'axios'; import gsap from 'gsap'; import ScrollTrigger from 'gsap/ScrollTrigger'; import { isEqual, isMobile, setStatusAndNavBarStyles } from 'utils'; export function useComponentWillMount(willMountCallback: () => () => void) { // NOTE:(REACT) using useRef because useState will re-render the component. const ref: { current: boolean | (() => void) } = useRef(false); if (!ref.current) { ref.current = willMountCallback() || true; } useEffect(() => { if (typeof ref.current === 'function') { return ref.current; } }, []); return ref; } function useDeepCompareMemoize(value: any) { const ref: { current: any } = useRef(); if (!isEqual(value, ref.current)) { ref.current = value; } return ref.current; } /** * Same as useEffect but deep compares dependencies */ export function useDeepCompareEffect(callback: () => void, dependencies: any[]) { useEffect(callback, dependencies.map(useDeepCompareMemoize)); } /** * Same as useMemo but deep compares dependencies */ export function useDeepCompareMemo(callback: () => void, dependencies: any[]) { return useMemo(callback, dependencies.map(useDeepCompareMemoize)); } const NoErrorObj = { isError: false, errorMsg: '' }; type useApiProps = (...args: any) => AxiosPromise; type fetchResponce = (value: AxiosResponse) => void; type fetchReject = (error: any) => void; export function useApi(api: useApiProps) { const axiosCancelToken = useRef(null); const [isLoading, setIsLoading] = useState(false); const [{ isError, errorMsg }, setIsError] = useState(NoErrorObj); function fetch(...args: any) { if (isLoading) { cancel(); } else { setIsLoading(true); setIsError(NoErrorObj); } axiosCancelToken.current = new AbortController(); return new Promise((res: fetchResponce, rej: fetchReject) => { api(axiosCancelToken.current.signal, ...args) .then((response) => { setIsLoading(false); res(response); }) .catch((error) => { setIsLoading(false); setIsError({ isError: true, errorMsg: error }); rej(error); }); }); } function cancel() { axiosCancelToken.current.abort(); } return { fetch, cancel, isL: isLoading, isE: isError, errorMsg }; } type UseRefStateReturns = [T, (updatedValue: T) => void, () => T]; /** * same as use state, but we get a third param to get current value. This will be useful while working with settimeout, eventHandlers, promises and axios api calls. */ export function useRefState(defaultValue: T): UseRefStateReturns { const ref = useRef(defaultValue); const [state, setState] = useState(defaultValue); function setStateFn(updatedValue: any) { ref.current = updatedValue; setState(updatedValue); } function getValueFn() { return ref.current; } return [state, setStateFn, getValueFn]; } export function useFallbackState( defaultValue?: any, parentState?: any, setParentState?: React.Dispatch ) { const parentStateUndefined = parentState === undefined; const [state, setState] = useState(parentStateUndefined ? defaultValue : parentState); const localState = parentStateUndefined ? state : parentState; // eslint-disable-next-line @typescript-eslint/no-explicit-any function setLocalState(latestState: any) { setState(latestState); if (typeof setParentState === 'function') { setParentState(latestState); } } return [localState, setLocalState]; } export function useSetMobilePreference() { if (isMobile) { setStatusAndNavBarStyles(); } } export function useSetAppPreference() { gsap.registerPlugin(ScrollTrigger); useSetMobilePreference(); }