UNPKG

react-hooks-global-state-next

Version:
1 lines 8.56 kB
{"version":3,"file":"index.modern.js","sources":["../src/createGlobalState.ts","../src/createStore.ts"],"sourcesContent":["import { SetStateAction, useCallback } from 'react';\n\nimport { create } from 'zustand';\n\nconst validateStateKey = (keys: string[], stateKey: string) => {\n if (!keys.includes(stateKey)) {\n throw new Error(`'${stateKey}' not found. It must be provided in initialState as a property key.`);\n }\n};\n\nconst isFunction = (fn: unknown): fn is Function => (typeof fn === 'function');\n\nconst updateValue = <Value>(oldValue: Value, newValue: SetStateAction<Value>) => (\n isFunction(newValue) ? newValue(oldValue) : newValue\n);\n\n/**\n * Create a global state.\n *\n * It returns a set of functions\n * - `useGlobalState`: a custom hook works like React.useState\n * - `getGlobalState`: a function to get a global state by key outside React\n * - `setGlobalState`: a function to set a global state by key outside React\n * - `subscribe`: a function that subscribes to state changes\n *\n * @example\n * import { createGlobalState } from 'react-hooks-global-state-next';\n *\n * const { useGlobalState } = createGlobalState({ count: 0 });\n *\n * const Component = () => {\n * const [count, setCount] = useGlobalState('count');\n * ...\n * };\n */\nexport const createGlobalState = <State extends object>(initialState: State) => {\n const useStore = create<State>(() => initialState);\n\n type StateKeys = keyof State;\n const keys = Object.keys(initialState);\n\n const setGlobalState = <StateKey extends StateKeys>(\n stateKey: StateKey,\n update: SetStateAction<State[StateKey]>,\n ) => {\n if (process.env.NODE_ENV !== 'production') {\n validateStateKey(keys, stateKey as string);\n }\n useStore.setState((previousState) => ({\n [stateKey]: updateValue(previousState[stateKey], update),\n } as Pick<State, StateKey> as Partial<State>));\n };\n\n const useGlobalState = <StateKey extends StateKeys>(stateKey: StateKey) => {\n if (process.env.NODE_ENV !== 'production') {\n validateStateKey(keys, stateKey as string);\n }\n const selector = useCallback((state: State) => state[stateKey], [stateKey]);\n const partialState = useStore(selector);\n const updater = useCallback(\n (u: SetStateAction<State[StateKey]>) => setGlobalState(stateKey, u),\n [stateKey],\n );\n return [partialState, updater] as const;\n };\n\n const getGlobalState = <StateKey extends StateKeys>(stateKey: StateKey) => {\n if (process.env.NODE_ENV !== 'production') {\n validateStateKey(keys, stateKey as string);\n }\n return useStore.getState()[stateKey];\n };\n\n const subscribe = <StateKey extends StateKeys>(\n stateKey: StateKey,\n listener: (value: State[StateKey]) => void,\n ) => {\n useStore.subscribe((state, prevState) => {\n if (state[stateKey] !== prevState[stateKey]) {\n listener(state[stateKey]);\n }\n });\n };\n\n return {\n useGlobalState,\n getGlobalState,\n setGlobalState,\n subscribe,\n };\n};\n","/* eslint @typescript-eslint/no-explicit-any: off */\n\nimport { Reducer, SetStateAction, useCallback } from 'react';\n\nimport { create } from 'zustand';\nimport { redux } from 'zustand/middleware';\n\ntype ExtractState<S> = S extends {\n getState: () => infer T;\n} ? T : never;\n\nconst validateStateKey = (keys: string[], stateKey: string) => {\n if (!keys.includes(stateKey)) {\n throw new Error(`'${stateKey}' not found. It must be provided in initialState as a property key.`);\n }\n};\n\nconst isFunction = (fn: unknown): fn is Function => (typeof fn === 'function');\n\nconst updateValue = <Value>(oldValue: Value, newValue: SetStateAction<Value>) => (\n isFunction(newValue) ? newValue(oldValue) : newValue\n);\n\n/**\n * Create a global store.\n *\n * It returns a set of functions\n * - `useStoreState`: a custom hook to read store state by key\n * - `getState`: a function to get store state by key outside React\n * - `dispatch`: a function to dispatch an action to store\n *\n * A store works somewhat similarly to Redux, but not the same.\n *\n * @example\n * import { createStore } from 'react-hooks-global-state-next';\n *\n * const initialState = { count: 0 };\n * const reducer = ...;\n *\n * const store = createStore(reducer, initialState);\n * const { useStoreState, dispatch } = store;\n *\n * const Component = () => {\n * const count = useStoreState('count');\n * ...\n * };\n */\nexport const createStore = <State extends object, Action extends { type: unknown }>(\n reducer: Reducer<State, Action>,\n initialState: State = (reducer as any)(undefined, { type: undefined }),\n enhancer?: any,\n): Store<State, Action> => {\n if (enhancer) return enhancer(createStore)(reducer, initialState);\n\n const useStore = create(redux(reducer as any, initialState));\n\n type BoundState = ExtractState<typeof useStore>;\n type StateKeys = keyof BoundState;\n const keys = Object.keys(initialState);\n\n const useStoreState = <StateKey extends StateKeys>(stateKey: StateKey) => {\n if (process.env.NODE_ENV !== 'production') {\n validateStateKey(keys, stateKey as string);\n }\n const selector = useCallback(\n (state: BoundState) => state[stateKey],\n [stateKey],\n );\n return useStore(selector);\n };\n\n const useGlobalState = <StateKey extends StateKeys>(stateKey: StateKey) => {\n if (process.env.NODE_ENV !== 'production') {\n // eslint-disable-next-line no-console\n console.warn('[DEPRECATED] useStoreState instead');\n }\n const partialState = useStoreState(stateKey);\n const updater = useCallback(\n (update: SetStateAction<BoundState[StateKey]>) => {\n useStore.setState((previousState) => ({\n [stateKey]: updateValue(previousState[stateKey], update),\n } as Pick<BoundState, StateKey> as Partial<BoundState>));\n },\n [stateKey],\n );\n return [partialState, updater] as const;\n };\n\n return {\n useStoreState,\n useGlobalState,\n getState: useStore.getState,\n dispatch: useStore.dispatch,\n } as unknown as Store<State, Action>;\n};\n\ntype Store<State, Action> = {\n useStoreState: <StateKey extends keyof State>(stateKey: StateKey) => State[StateKey];\n /**\n * useGlobalState created by createStore is deprecated.\n *\n * @deprecated useStoreState instead\n */\n useGlobalState: <StateKey extends keyof State>(stateKey: StateKey) => readonly [\n State[StateKey],\n (u: SetStateAction<State[StateKey]>) => void,\n ];\n getState: () => State;\n dispatch: (action: Action) => Action;\n};\n"],"names":["validateStateKey","keys","stateKey","includes","Error","createGlobalState","initialState","useStore","create","Object","setGlobalState","update","process","env","NODE_ENV","setState","previousState","oldValue","newValue","useGlobalState","selector","useCallback","state","u","getGlobalState","getState","subscribe","listener","prevState","createStore","reducer","undefined","type","enhancer","redux","useStoreState","console","warn","dispatch"],"mappings":"gHAIA,MAAsBA,EAAG,CAACC,EAAgBC,KACxC,IAAKD,EAAKE,SAASD,GACjB,MAAUE,IAAAA,UAAUF,uEACrB,EA4BUG,EAA2CC,IACtD,MAAcC,EAAGC,EAAc,IAAMF,KAGxBG,OAAOR,KAAKK,GAELI,EAAG,CACrBR,EACAS,KAE6B,eAAzBC,QAAQC,IAAIC,UACdd,EAAiBC,EAAMC,GAEzBK,EAASQ,SAAUC,IAAD,OAChBd,CAACA,IArCqBe,EAqCED,EAAcd,GArCCgB,EAqCUP,EAvCY,mBAGtDO,EAAYA,EAASD,GAAYC,IAD1B,IAAQD,EAAiBC,CAoCzC,EAAA,EAoCF,MAAO,CACLC,eAhCkDjB,IACrB,eAAzBU,QAAQC,IAAIC,UACdd,EAAiBC,EAAMC,GAEzB,MAAckB,EAAGC,EAAaC,GAAiBA,EAAMpB,GAAW,CAACA,IAMjE,MAAO,CALcK,EAASa,GACdC,EACbE,GAAuCb,EAAeR,EAAUqB,GACjE,CAACrB,IAEI,EAuBPsB,eApBkDtB,IACrB,eAAzBU,QAAQC,IAAIC,UACdd,EAAiBC,EAAMC,GAElBK,EAASkB,WAAWvB,IAiB3BQ,iBACAgB,UAfgB,CAChBxB,EACAyB,KAEApB,EAASmB,UAAU,CAACJ,EAAOM,KACrBN,EAAMpB,KAAc0B,EAAU1B,IAChCyB,EAASL,EAAMpB,GAChB,EAHH,EAOK,ECrCI2B,EAAc,CACzBC,EACAxB,EAAuBwB,OAAgBC,EAAW,CAAEC,UAAMD,IAC1DE,KAEA,GAAIA,EAAU,OAAOA,EAASJ,EAATI,CAAsBH,EAASxB,GAEpD,MAAcC,EAAGC,EAAO0B,EAAMJ,EAAgBxB,MAIjCG,OAAOR,KAAKK,GAEN6B,EAAgCjC,IACpB,eAAzBU,QAAQC,IAAIC,UAlDK,EAACb,EAAgBC,KACxC,IAAKD,EAAKE,SAASD,GACjB,MAAUE,IAAAA,UAAUF,uEACrB,EAgDGF,CAAiBC,EAAMC,GAEzB,MAAckB,EAAGC,EACdC,GAAsBA,EAAMpB,GAC7B,CAACA,IAEH,OAAOK,EAASa,EAAD,EAoBjB,MAAO,CACLe,gBACAhB,eAnBkDjB,IACrB,eAAzBU,QAAQC,IAAIC,UAEdsB,QAAQC,KAAK,sCAWR,CATcF,EAAcjC,GACnBmB,EACbV,IACCJ,EAASQ,SAAUC,IAAmB,OACpCd,CAACA,IA7DiBe,EA6DMD,EAAcd,GA7DHgB,EA6DcP,EA/DQ,mBAGtDO,EAAYA,EAASD,GAAYC,IAD1B,IAAQD,EAAiBC,CA4DrC,EAAA,EAIF,CAAChB,MAQHuB,SAAUlB,EAASkB,SACnBa,SAAU/B,EAAS+B,SAJd"}