import { State, ActionTypes, usePromisifiedDispatch, Controller, __INTERNAL__, } from '@rest-hooks/react'; import { StateContext, ControllerContext, StoreContext, BackupBoundary, } from '@rest-hooks/react'; import React, { useEffect, useState, useMemo, useRef, useCallback, } from 'react'; const { createReducer } = __INTERNAL__; interface Store { subscribe(listener: () => void): () => void; dispatch: React.Dispatch; getState(): S; } interface Props { children: React.ReactNode; store: Store; selector: (state: S) => State; controller: Controller; } /** * Like CacheProvider, but for an external store * @see https://dataclient.io/docs/api/ExternalCacheProvider */ export default function ExternalCacheProvider({ children, store, selector, controller, }: Props) { const masterReducer = useMemo(() => createReducer(controller), [controller]); const selectState = useCallback(() => { const state = selector(store.getState()); return state.optimistic.reduce(masterReducer, state); }, [masterReducer, selector, store]); const [state, setState] = useState(selectState); const isMounted = useRef(true); useEffect(() => { isMounted.current = true; () => { isMounted.current = false; }; }, []); useEffect(() => { const unsubscribe = store.subscribe(() => { if (isMounted.current) setState(selectState()); }); return unsubscribe; }, [selectState, store]); const dispatch = usePromisifiedDispatch(store.dispatch, state); const adaptedStore = useMemo(() => { return { ...store, getState: () => selector(store.getState()) }; }, [selector, store]); return ( {children} ); }