Skip to content

Instantly share code, notes, and snippets.

@SeedyROM
Last active February 20, 2021 23:53
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save SeedyROM/af582797077471270df4c9dcbb18b305 to your computer and use it in GitHub Desktop.
Save SeedyROM/af582797077471270df4c9dcbb18b305 to your computer and use it in GitHub Desktop.
TypeScript/React Context Store
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;
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,
};
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);
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