Created
December 6, 2023 15:04
-
-
Save syntax-punk/7edaa96ea20ea634babd90f55568f8f7 to your computer and use it in GitHub Desktop.
"mini store" - a ridiculously simple global store implementation
This file contains hidden or 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
| export type ActionFunction<T> = (prev: T) => T; | |
| export type Store<T> = { | |
| getState: () => T; | |
| setState: (action: T | ActionFunction<T>) => void; | |
| subscribe: (callback: VoidFunction) => VoidFunction; | |
| }; | |
| export const createStore = <T extends unknown>(initialState: T): Store<T> => { | |
| let state = initialState; | |
| const callbacks = new Set<() => void>(); | |
| const getState = () => state; | |
| const setState = (nextState: T | ActionFunction<T>) => { | |
| state = | |
| typeof nextState === "function" | |
| ? (nextState as ActionFunction<T>)(state) | |
| : nextState; | |
| callbacks.forEach((callback) => callback()); | |
| }; | |
| const subscribe = (callback: () => void) => { | |
| callbacks.add(callback); | |
| return () => { | |
| callbacks.delete(callback); | |
| }; | |
| }; | |
| return { getState, setState, subscribe }; | |
| }; |
This file contains hidden or 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 { ActionFunction, createStore } from "./ministore"; | |
| import { useStore } from "./useStore"; | |
| let store = createStore({ count: 0 }); | |
| export function ComponentA() { | |
| const [state, setState] = useStore(store); | |
| const inc = () => { | |
| setState((prev) => ({ | |
| ...prev, | |
| count: prev.count + 1, | |
| })); | |
| }; | |
| return ( | |
| <div> | |
| <h1>Component - A</h1> | |
| <h1>{state.count}</h1> | |
| <button onClick={inc}>+1</button> | |
| </div> | |
| ); | |
| } | |
| export const ComponentB = () => { | |
| const [state, setState] = useStore(store); | |
| const inc2 = () => { | |
| setState((prev) => ({ | |
| ...prev, | |
| count: prev.count + 2, | |
| })); | |
| }; | |
| return ( | |
| <div> | |
| <h1>Component - B</h1> | |
| <h1>{state.count}</h1> | |
| <button onClick={inc2}>+2</button> | |
| </div> | |
| ); | |
| }; | |
This file contains hidden or 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 { useEffect, useState } from "react" | |
| import { Store } from "./ministore"; | |
| export const useStore = <T extends unknown>(store: Store<T>) => { | |
| const [state, setState] = useState(store.getState()); | |
| useEffect(() => { | |
| const unsubscribe = store.subscribe(() => { | |
| setState(store.getState()); | |
| }); | |
| setState(store.getState()); | |
| return unsubscribe; | |
| }, [store]); | |
| return [state, store.setState] as const; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment