Last active
February 20, 2021 23:53
-
-
Save SeedyROM/af582797077471270df4c9dcbb18b305 to your computer and use it in GitHub Desktop.
TypeScript/React Context Store
This file contains 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, { Dispatch, Reducer } from "react"; | |
const createStore = | |
<S extends {}, A extends {}> | |
(reducer: Reducer<S, A>, initialState: S) => | |
{ | |
const contextValues: [S, Dispatch<A>] = [ | |
initialState, | |
(action) => {}, | |
]; | |
const Context = React.createContext<[S, Dispatch<A>]>(contextValues); | |
const Provider: React.FC = (props: any) => { | |
const store = React.useReducer(reducer, initialState); | |
return ( | |
<Context.Provider value={store}> | |
{props.children} | |
</Context.Provider> | |
); | |
}; | |
return { Context, Provider, Consumer: Context.Consumer }; | |
}; | |
export default createStore; |
This file contains 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 isEqual from "lodash/isEqual"; | |
// Types for testing | |
import { ICartItem } from "../types/Cart"; | |
import createStore from '../helpers/createStore'; | |
type State = ICartItem[]; | |
type Action = | |
| { type: "add" | "remove", item: ICartItem } | |
| { type: "clear" }; | |
const initialState: State = []; | |
const reducer = (state: ICartItem[], action: Action) => { | |
switch(action.type) { | |
case "add": | |
return [...state, action.item]; | |
case "remove": | |
return state.filter((item) => !isEqual(item, action.item)); | |
case "clear": | |
return []; | |
default: | |
return state; | |
} | |
}; | |
const { Context, Provider, Consumer } = createStore(reducer, initialState); | |
export { | |
Context, | |
Provider, | |
Consumer, | |
}; |
This file contains 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 { Context as CartContext, Provider as CartProvider } from '../../state/CartContext'; | |
import { ICartItem } from "../../types/Cart"; | |
import withProvider from "../../helpers/withProvider"; | |
const testItem: ICartItem = { | |
_id: 1, | |
name: "Books", | |
quantity: 1 | |
}; | |
const Cart: React.FC = () => { | |
const [items, dispatch] = React.useContext(CartContext); | |
const addItem = () => dispatch({type: "add", item: testItem}); | |
const removeItem = () => dispatch({type: "remove", item: testItem}); | |
return ( | |
<> | |
<div> | |
<button onClick={addItem}>Add item</button> | |
</div> | |
<div> | |
<button onClick={removeItem}>Remove item</button> | |
</div> | |
<div> | |
{items && items.map((item, i) => <div key={i}>{item.name}</div>)} | |
</div> | |
</> | |
); | |
}; | |
export default withProvider(CartProvider)(Cart); |
This file contains 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"; | |
const withProvider: React.FC = | |
(Provider: any) => | |
(Component: any) => | |
(props: any) => | |
( | |
<Provider> | |
<Component {...props} /> | |
</Provider> | |
); | |
export default withProvider; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment