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.

Revisions

  1. NitsanBaleli revised this gist Mar 18, 2021. No changes.
  2. NitsanBaleli created this gist Mar 18, 2021.
    39 changes: 39 additions & 0 deletions makeStore.ts
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,39 @@
    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];
    }