Skip to content

Instantly share code, notes, and snippets.

@NitsanBaleli
Created March 18, 2021 20:17
Show Gist options
  • Save NitsanBaleli/74f20be2a5960a9fb5c93e29577126a8 to your computer and use it in GitHub Desktop.
Save NitsanBaleli/74f20be2a5960a9fb5c93e29577126a8 to your computer and use it in GitHub Desktop.
import * as React from "react";
import { useState, useMemo, Dispatch, SetStateAction } from "react";
type IContext<T> = [T, Dispatch<SetStateAction<T>>];
type ProviderProps<T> = { initialValue: T; children: React.ReactNode };
export function makeStore<T>(): [
(props: ProviderProps<T>) => React.ReactElement,
() => IContext<T>
] {
// Make a context for the store
const context = React.createContext<IContext<T>>(null);
// Make a provider that takes an initialValue
const Provider = ({ initialValue, children }: ProviderProps<T>) => {
// Make a new state instance (could even use immer here!)
const [state, setState] = useState<T>(initialValue);
// Memoize the context value to update when the state does
const contextValue = useMemo<IContext<T>>(() => [state, setState], [
state,
]);
// Provide the store to children
return (
<context.Provider value={contextValue}>{children}</context.Provider>
);
};
// A hook to help consume the store
const useStore = () => {
const _context = React.useContext<IContext<T>>(context);
if (_context === undefined) {
throw new Error("context must be used inside its Provider");
}
return _context;
};
return [Provider, useStore];
}
@NitsanBaleli
Copy link
Author

const [StoreProvider, useStore] = makeStore<IState>();

export { StoreProvider, useStore };

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment