import * as React from "react"; import { useState, useMemo, Dispatch, SetStateAction } from "react"; type IContext = [T, Dispatch>]; type ProviderProps = { initialValue: T; children: React.ReactNode }; export function makeStore(): [ (props: ProviderProps) => React.ReactElement, () => IContext ] { // Make a context for the store const context = React.createContext>(null); // Make a provider that takes an initialValue const Provider = ({ initialValue, children }: ProviderProps) => { // Make a new state instance (could even use immer here!) const [state, setState] = useState(initialValue); // Memoize the context value to update when the state does const contextValue = useMemo>(() => [state, setState], [ state, ]); // Provide the store to children return ( {children} ); }; // A hook to help consume the store const useStore = () => { const _context = React.useContext>(context); if (_context === undefined) { throw new Error("context must be used inside its Provider"); } return _context; }; return [Provider, useStore]; }