Advertisement
Guest User

Redux Clone Using Context

a guest
Jan 20th, 2020
89
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. //STORE JS -----------------------------------------------------------------------------
  2.  
  3. import React, {ReactElement, useState} from "react";
  4.  
  5. /* Do not do this in production! Super inefficient! */
  6.  
  7. interface IStoreState {
  8.     episodes: string[];
  9.     favorites: string[];
  10.     dispatchStore: <T extends StoreStateAction>(action: T) => void;
  11. }
  12.  
  13. const initialState: IStoreState = {
  14.     episodes: [],
  15.     favorites: [],
  16.     dispatchStore: <T extends StoreStateAction>(action: T) => {}
  17. };
  18.  
  19.  
  20. //Define actions here
  21. enum ActionType {
  22.     AddEpisode
  23. };
  24.  
  25. interface StoreStateAction {
  26.     type: ActionType
  27. }
  28.  
  29. class AddEpisodeAction implements StoreStateAction {
  30.     type: ActionType;
  31.     episode: string;
  32.  
  33.     constructor(episode: string) {
  34.         this.type = ActionType.AddEpisode;
  35.         this.episode = episode;
  36.     }
  37. }
  38.  
  39. //Action Creation Functions Here
  40. export const addEpisodeAction = (episode: string): AddEpisodeAction => {return new AddEpisodeAction(episode);};
  41.  
  42. //Global reducer
  43. const reducer = <T extends StoreStateAction> (state: IStoreState, action: T): IStoreState => {
  44.     switch (action.type) {
  45.         case ActionType.AddEpisode:
  46.             if (action instanceof AddEpisodeAction) {
  47.                 return {
  48.                     episodes: state.episodes.concat([action.episode]),
  49.                     favorites: state.favorites,
  50.                     dispatchStore: state.dispatchStore
  51.                }
  52.             }
  53.             return state;
  54.         default:
  55.             return state;
  56.     }
  57. };
  58.  
  59. export const Store = React.createContext<IStoreState>(initialState);
  60.  
  61.  
  62. export const StoreProvider = (props: any): ReactElement => {
  63.    
  64.   const dispatchStore = <T extends StoreStateAction>(action: T): void => {
  65.      setStoreState((state) => reducer(state, action));
  66.   }
  67.  
  68.   //Mutable state
  69.   const [storeState, setStoreState] = useState<IStoreState>({episodes: initialState.episodes, favorites: initialState.favorites, dispatchStore});
  70.  
  71.   return (
  72.   <Store.Provider value={storeState}>
  73.       {props.children}
  74.   </Store.Provider>  
  75.   );
  76. };
  77.  
  78. //EXAMPLE USAGE ----------------------------------------------------------
  79.  
  80. import React, { ReactElement, useContext, useState, FormEvent } from 'react';
  81. import {Store, addEpisodeAction} from "./Store";
  82.  
  83. const App: React.FC = (): ReactElement => {
  84.   const ctx = useContext(Store);
  85.   const [episode, setEpisode] = useState<string>("");
  86.  
  87.   const onSubmit = (e: FormEvent): void => {
  88.     e.preventDefault();
  89.     ctx.dispatchStore(addEpisodeAction(episode));
  90.     setEpisode("");
  91.   };
  92.  
  93.   return (
  94.     <React.Fragment>
  95.       <h1>Rick and Morty</h1>
  96.       <p>Pick your favorite episode!</p>
  97.       <form onSubmit={onSubmit}>
  98.         <input type="text" value={episode} onChange={(e) => setEpisode(e.target.value)}/>
  99.         <button>Add</button>
  100.       </form>
  101.       {ctx.episodes.map((episode: string, i: number): ReactElement => <p key={i}>{episode}</p>)}
  102.     </React.Fragment>
  103.   );
  104. }
  105.  
  106. export default App;
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement