Created
September 27, 2019 17:57
-
-
Save GingerBear/f66fed96b0404049d796857c980ca4d1 to your computer and use it in GitHub Desktop.
Util function to create type safe state management store with useContext and useReducer
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* | |
* Util function to create type safe state management store with useContext and useReducer. | |
* The mechanism is described by https://kentcdodds.com/blog/how-to-use-react-context-effectively/ | |
* | |
*/ | |
import React, { useReducer, createContext, useContext } from 'react'; | |
export type ContextProviderProps = { children: React.ReactNode }; | |
export function createContextProvider<StateT, ActionT>( | |
reducer: (state: StateT, action: ActionT) => StateT, | |
initialState: StateT | |
) { | |
type Dispatch = (action: ActionT) => void; | |
const StateContext = createContext<StateT | undefined>(undefined); | |
const DispatchContext = createContext<Dispatch | undefined>(undefined); | |
function ContextProvider({ children }: ContextProviderProps) { | |
const [state, dispatch] = useReducer(reducer, initialState); | |
return ( | |
<StateContext.Provider value={state}> | |
<DispatchContext.Provider value={dispatch}> | |
{children} | |
</DispatchContext.Provider> | |
</StateContext.Provider> | |
); | |
} | |
function useContextState() { | |
const context = useContext(StateContext); | |
if (context === undefined) { | |
throw new Error('useContextState must be used with a ContextProvider'); | |
} | |
return context; | |
} | |
function useContextDispatch() { | |
const context = useContext(DispatchContext); | |
if (context === undefined) { | |
throw new Error('useContextDispatch must be used with a ContextProvider'); | |
} | |
return context; | |
} | |
return [ContextProvider, useContextState, useContextDispatch] as [ | |
typeof ContextProvider, | |
typeof useContextState, | |
typeof useContextDispatch | |
]; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment