UNPKG

@graffy/react

Version:

This built-in module provides an idiomatic React API to a Graffy store.

95 lines (94 loc) 2.58 kB
import PropTypes from "prop-types"; import React from "react"; import isEqual from "lodash/isEqual.js"; const { createContext } = React; const GraffyContext = createContext(null); function GraffyProvider({ store, children }) { return /* @__PURE__ */ React.createElement(GraffyContext.Provider, { value: store }, children); } GraffyProvider.propTypes = { store: PropTypes.object.isRequired, children: PropTypes.node }; const { useRef, useState, useEffect, useContext: useContext$1 } = React; const consumeSubscription = async (subscription, setState) => { try { for await (const data of subscription) { if (subscription.closed) { break; } setState((prevState) => ({ ...prevState, loading: false, data, error: null })); } } catch (error) { setState((prevState) => ({ ...prevState, loading: false, data: null, error })); } }; const retrieveResult = async (promise, setState) => { try { const data = await promise; setState((prevState) => ({ ...prevState, loading: false, data, error: null })); } catch (error) { setState((prevState) => ({ ...prevState, loading: false, data: null, error })); } }; function useQuery(query, { once = false, ...other } = {}) { const store = useContext$1(GraffyContext); const queryRef = useRef(null); if (!store) throw Error("graffy_react.no_store_in_context"); const queryHasChanged = !isEqual(queryRef.current, query); if (queryHasChanged) { queryRef.current = query; } const fetchData = (options = other) => { if (state.loading !== true) setState({ ...state, loading: true }); if (once) { retrieveResult(store.read(query, options), setState); } else { const subscription = store.watch(query, options); consumeSubscription(subscription, setState); return () => { subscription.closed = true; subscription.return(); }; } }; const refetch = fetchData.bind(null, { ...other, skipCache: true }); const [state, setState] = useState({ loading: true }); useEffect(fetchData, [queryRef.current, store]); return once ? { ...state, refetch } : state; } function Query({ query, options, children }) { const { data, loading, error } = useQuery(query, options); return children({ data, loading, error }); } const { useContext } = React; function useStore() { const store = useContext(GraffyContext); return store; } export { GraffyProvider, Query, useQuery, useStore };