Skip to content

Instantly share code, notes, and snippets.

@Brenndoerfer
Created September 5, 2021 09:36
Show Gist options
  • Select an option

  • Save Brenndoerfer/3713aa4ae68209fb2c35875bd1fe5dae to your computer and use it in GitHub Desktop.

Select an option

Save Brenndoerfer/3713aa4ae68209fb2c35875bd1fe5dae to your computer and use it in GitHub Desktop.
Generic Context.Provider for React
import React, { ReactNode, useReducer } from 'react';
interface Reducer<T, R extends ActionProps> {
(state: T, action: R): any;
}
interface Dispatch<T extends ActionProps> {
(action: T): void;
}
interface ActionProps {
readonly type: string;
readonly payload?: any;
}
interface Action<T extends ActionProps> {
(dispatch: Dispatch<T>): (
arg1?: any,
arg2?: any,
arg3?: any,
callback?: any
) => void;
}
interface Actions<S extends ActionProps> {
[propName: string]: Action<S>;
}
function createDataContext<T, R, S extends ActionProps>(
reducer: Reducer<R, S>,
actions: Actions<S>,
initialState: R
) {
const Context = React.createContext<T>({} as T);
const Provider = ({ children }: { children: ReactNode }) => {
const [state, dispatch] = useReducer(reducer, initialState);
// actions === { addBlogPost: (dispatch) => { return () => {} }}
const boundActions = {} as any;
for (let key in actions) {
boundActions[key] = actions[key](dispatch);
}
return (
<Context.Provider value={{ state, ...boundActions }}>
{children}
</Context.Provider>
);
};
return { Context, Provider };
}
export default createDataContext;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment