Skip to content

Instantly share code, notes, and snippets.

@GingerBear
Created September 27, 2019 17:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save GingerBear/f66fed96b0404049d796857c980ca4d1 to your computer and use it in GitHub Desktop.
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
/**
*
* 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