Skip to content

Instantly share code, notes, and snippets.

@vhuerta
Last active March 9, 2020 18:21
Show Gist options
  • Select an option

  • Save vhuerta/ff46f9ddf2af2ad1a03938877473c484 to your computer and use it in GitHub Desktop.

Select an option

Save vhuerta/ff46f9ddf2af2ad1a03938877473c484 to your computer and use it in GitHub Desktop.
import { useCallback, Reducer, ReducerState, ReducerAction } from "react";
import { useReducer } from "reinspect";
export type StateGetter<A extends Reducer<any, any>> = () => ReducerState<A>;
export type DispatchThunk<A extends Reducer<any, any>> = (
dispatch: (value: ReducerAction<A>) => void,
state: StateGetter<A>
) => void;
export type DispatcherThunk<A extends Reducer<any, any>> = (
action: ReducerAction<A> | DispatchThunk<A>
) => void;
export type ActionOrThunk<A extends Reducer<any, any>> =
| ReducerAction<A>
| DispatchThunk<A>;
function isDispatchThunk<R extends Reducer<any, any>>(
action: ReducerAction<R> | DispatchThunk<R>
): action is DispatchThunk<R> {
return typeof action === "function";
}
/**
* Augments React's useReducer() hook so that the action
* dispatcher supports thunks.
*/
export function useThunkReducer<R extends Reducer<any, any>>(
reducer: R,
initialState: ReducerState<R>,
id: string
): [ReducerState<R>, DispatcherThunk<R>] {
const [state, dispatch] = useReducer(
reducer,
initialState,
state => state,
id
);
const getState = useCallback(() => state, [state]);
const dispatchThunk = (action: ActionOrThunk<R>): void => {
return isDispatchThunk(action)
? action(dispatch, getState)
: dispatch(action);
};
return [state, dispatchThunk];
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment