UNPKG

@dr.pogodin/react-global-state

Version:
90 lines (87 loc) 3.54 kB
import { createContext, use, useState } from 'react'; import GlobalState from "./GlobalState.js"; 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(throwWithoutSsrContext = 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 = ({ children, ...rest }) => { const [localState, setLocalState] = useState(); let state; // Below we cast `rest.stateProxy` as "boolean" for safe backward // compatibility with plain JavaScript (as TypeScript typings only // permit "true" or GlobalState value; while legacy codebase may // pass in a boolean value here, occasionally equal "false"). if ('stateProxy' in rest && rest.stateProxy) { if (localState) setLocalState(undefined); state = rest.stateProxy === true ? getGlobalState() : rest.stateProxy; } else if (localState) { state = localState; } else { const { initialState, ssrContext } = rest; state = new GlobalState(typeof initialState === 'function' ? initialState() : initialState, ssrContext); setLocalState(state); } return /*#__PURE__*/_jsx(Context, { value: state, children: children }); }; export default GlobalStateProvider; //# sourceMappingURL=GlobalStateProvider.js.map