Last active
April 29, 2020 08:42
-
-
Save rpCal/4a58ff9b14dc777ba09bcd99a7ca362d to your computer and use it in GitHub Desktop.
typescript/react/immerjs - React.useReducer + hooks
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
import React from "react"; | |
import { produce } from "immer"; | |
export interface ModalForm { | |
id: string | undefined; | |
} | |
export const initModalForm: ModalForm = { | |
id: undefined, | |
}; | |
type Action = { type: "setName"; payload: string }; | |
type Dispatch = (action: Action) => void; | |
type State = { | |
modalForm: ModalForm; | |
}; | |
type ContextProviderProps = { children: React.ReactNode }; | |
export const initalState: State = { | |
modalForm: { ...initModalForm }, | |
}; | |
const StateContext = React.createContext<State | undefined>(undefined); | |
const DispatchContext = React.createContext<Dispatch | undefined>(undefined); | |
function reducer(state: State, action: Action): State { | |
console.log("reducer: log", state, action.type, action.payload); | |
switch (action.type) { | |
case "setName": { | |
return produce(state, (draft) => { | |
draft.modalForm.id = action.payload; | |
}); | |
} | |
default: { | |
throw new Error(`Unhandled action type: ${(action as any).toString()}`); | |
} | |
} | |
} | |
function ContextProvider({ children }: ContextProviderProps) { | |
const [state, dispatch] = React.useReducer(reducer as any, initalState); | |
return ( | |
<StateContext.Provider value={state as any}> | |
<DispatchContext.Provider value={dispatch as Dispatch}> | |
{children} | |
</DispatchContext.Provider> | |
</StateContext.Provider> | |
); | |
} | |
function useContextState() { | |
const context = React.useContext(StateContext); | |
if (context === undefined) { | |
throw new Error("useContextState must be used within a Provider"); | |
} | |
return context; | |
} | |
function useContextDispatch() { | |
const context = React.useContext(DispatchContext); | |
if (context === undefined) { | |
throw new Error("useContextDispatch must be used within a Provider"); | |
} | |
return context; | |
} | |
export { ContextProvider, useContextState, useContextDispatch }; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment