UNPKG

sqlocal

Version:

SQLocal makes it easy to run SQLite3 in the browser, backed by the origin private file system.

67 lines (61 loc) 1.59 kB
import { useCallback, useMemo, useState, useSyncExternalStore, type Dispatch, type SetStateAction, } from 'react'; import type { SQLocal } from '../client.js'; import type { ReactiveQueryStatus, StatementInput } from '../types.js'; /** * A hook for using reactive SQL queries in React components. * @see {@link https://sqlocal.dev/api/reactivequery#react} */ export function useReactiveQuery<Result extends Record<string, any>>( db: SQLocal, query: StatementInput<Result> ): { data: Result[]; error: Error | undefined; status: ReactiveQueryStatus; setDb: Dispatch<SetStateAction<SQLocal>>; setQuery: Dispatch<SetStateAction<StatementInput<Result>>>; } { const [error, setError] = useState<Error | undefined>(undefined); const [pending, setPending] = useState<boolean>(true); const [dbValue, setDb] = useState(() => db); const [queryValue, setQuery] = useState(() => query); const reactiveQuery = useMemo(() => { setPending(true); return dbValue.reactiveQuery(queryValue); }, [dbValue, queryValue]); const get = useCallback(() => reactiveQuery.value, [reactiveQuery]); const subscribe = useCallback( (cb: () => void) => { const subscription = reactiveQuery.subscribe( () => { cb(); setError(undefined); setPending(false); }, (err) => { setError(err); } ); return () => { subscription.unsubscribe(); }; }, [reactiveQuery] ); const data = useSyncExternalStore(subscribe, get); const status = !!error ? 'error' : pending ? 'pending' : 'ok'; return { data, error, status, setDb, setQuery, }; }