Create Your Own Redux (Typescript)
2020-10-26
Prepare Initial States + State Type
export const initialState = { attributeA: { propertyA1: ``, }, attributeB: { propertyB1: 0, }, num: 0, }; export type StateType = { attributeA: { propertyA1: string; }; attributeB: { propertyB1: number; }; num: number; };
Prepare actions
type ActionMap<M extends { [index: string]: any }> = { [Key in keyof M]: M[Key] extends undefined ? { type: Key; } : { type: Key; payload: M[Key]; }; }; // eslint-disable-next-line no-shadow export enum ActionType { setAttrA = `SET_ATTR_A`, setAttrB = `SET_ATTR_B`, add = `ADD`, reduce = `REDUCE`, } /** * @name ActionPayload * @description Type def for action payloads, */ type ActionPayload = { [ActionType.setAttrA]: { propertyA1: string; }; [ActionType.setAttrB]: { propertyB1: number; }; /* Not payloads required for below 2 actions */ [ActionType.add]: undefined; [ActionType.reduce]: undefined; }; /** * @name ActionPayloadDataType * @description The type def of the Action Payload Data */ export type ActionPayloadDataType = ActionMap<ActionPayload>[keyof ActionMap<ActionPayload>];
Prepare the reducer details, NO EDIT STATE DIRECTLY
export const reducers = ( state: StateType, actionData: ActionPayloadDataType, ): StateType => { switch (actionData.type) { case ActionType.setAttrA: return { ...state, attributeA: { ...state.attributeA, ...actionData.payload, }, }; case ActionType.setAttrB: return { ...state, attributeB: { ...state.attributeB, ...actionData.payload, }, }; case ActionType.add: return { ...state, num: state.num + 1, }; case ActionType.reduce: return { ...state, num: state.num - 1, }; default: return state; } };
Create a HOC for state provider
export const AppContext = createContext<{ state: StateType; dispatch: React.Dispatch<ActionPayloadDataType>; }>({ state: initialState, dispatch: () => null, }); /** * @name StateProvider * @description A HOC to wrap root components for global state manage */ export const StateProvider: React.FC = ({ children }) => { const [state, dispatch] = useReducer(reducers, initialState); return ( <AppContext.Provider value={{ state, dispatch }}> {children} </AppContext.Provider> ); };
const App: React.FC = () => ( <StateProvider> <RootComponent/> </StateProvider> );
Now you can use it
const Camera: React.FC = () => { const { state, dispatch } = useContext(AppContext); return ( <div> {state.num} <button onClick={dispatch({ type: ActionType.add })}/> <button onClick={dispatch({ type: ActionType.setAttrB, payload: { propertyB1: 'dispatch this action to set property B1' }, })}/> </div> ); }; export default Camera;
关于本文
文章标题 | Create Your Own Redux (Typescript) |
发布日期 | 2020-10-26 |
文章分类 | Tech |
相关标签 | #Typescript #React |
留言板
PLACE_HOLDER
PLACE_HOLDER
PLACE_HOLDER
PLACE_HOLDER