UNPKG

@dr.pogodin/react-global-state

Version:
90 lines (88 loc) 3.49 kB
import { isFunction } from 'lodash'; import { createContext, use, useRef } from 'react'; import GlobalState from "./GlobalState"; import { jsx as _jsx } from "react/jsx-runtime"; const Context = /*#__PURE__*/createContext(null); /** * Gets {@link GlobalState} instance from the context. In most cases * you should use {@link useGlobalState}, and other hooks to interact with * the global state, instead of accessing it directly. * @return */ export function getGlobalState() { // TODO: Think about it: on one hand we on purpose called this function // as getGlobalState(), so that ppl looking for the state hook prefer using // useGlobalState(), while this getGlobalState() is reserved for nieche cases; // on the other hand, perhaps we can rename it into useSomething, to both // follow conventions, and to keep stuff clearly named at the same time. // eslint-disable-next-line react-hooks/rules-of-hooks const globalState = use(Context); if (!globalState) throw new Error('Missing GlobalStateProvider'); return globalState; } /** * @category Hooks * @desc Gets SSR context. * @param throwWithoutSsrContext If `true` (default), * this hook will throw if no SSR context is attached to the global state; * set `false` to not throw in such case. In either case the hook will throw * if the {@link <GlobalStateProvider>} (hence the state) is missing. * @returns SSR context. * @throws * - If current component has no parent {@link <GlobalStateProvider>} * in the rendered React tree. * - If `throwWithoutSsrContext` is `true`, and there is no SSR context attached * to the global state provided by {@link <GlobalStateProvider>}. */ export function getSsrContext() { let throwWithoutSsrContext = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true; const { ssrContext } = getGlobalState(); if (!ssrContext && throwWithoutSsrContext) { throw new Error('No SSR context found'); } return ssrContext; } /** * Provides global state to its children. * @param prop.children Component children, which will be provided with * the global state, and rendered in place of the provider. * @param prop.initialState Initial content of the global state. * @param prop.ssrContext Server-side rendering (SSR) context. * @param prop.stateProxy This option is useful for code * splitting and SSR implementation: * - If `true`, this provider instance will fetch and reuse the global state * from a parent provider. * - If `GlobalState` instance, it will be used by this provider. * - If not given, a new `GlobalState` instance will be created and used. */ const GlobalStateProvider = _ref => { let { children, ...rest } = _ref; const localStateRef = useRef(undefined); let state; // TODO: Revise. // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition if ('stateProxy' in rest && rest.stateProxy) { localStateRef.current = undefined; state = rest.stateProxy === true ? getGlobalState() : rest.stateProxy; } else { if (!localStateRef.current) { const { initialState, ssrContext } = rest; localStateRef.current = new GlobalState(isFunction(initialState) ? initialState() : initialState, ssrContext); } state = localStateRef.current; } return /*#__PURE__*/_jsx(Context, { value: state, children: children }); }; export default GlobalStateProvider; //# sourceMappingURL=GlobalStateProvider.js.map