Skip to content

Instantly share code, notes, and snippets.

@hunteva
Created January 13, 2020 00:06
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save hunteva/6e41f018264e2103b529353a814e309d to your computer and use it in GitHub Desktop.
Save hunteva/6e41f018264e2103b529353a814e309d to your computer and use it in GitHub Desktop.
A Tiny Global State hooks provide immutability via session-storage and strong type check against StateShape
import { useState, useEffect, useRef } from 'react';
import { getState, setState } from './session-storage';
import { StateShape } from './types';
type StateKey = keyof StateShape;
const TriggersMap = new Map<StateKey, Set<Function>>();
const triggerRenderById = (id: StateKey) => {
const triggers = TriggersMap.get(id) || new Set([]);
triggers.forEach(trigger => trigger(Date.now()));
};
const setupTriggers = (id: StateKey, trigger: (_: any) => void): (() => void) => {
const triggers = TriggersMap.get(id) || new Set();
triggers.add(trigger);
TriggersMap.set(id, triggers);
return () => triggers.delete(trigger);
};
export const useGlobalState = <K extends StateKey>(
id: K,
initValue: StateShape[K] | undefined
): [StateShape[K] | undefined, (payload: StateShape[K]) => void] => {
const [_, trigger] = useState(id);
const ref = useRef({ firstRender: true, compId: id });
const { firstRender, compId } = ref.current;
if (compId !== id) {
throw new Error("id should not change during component's life cycle");
}
useEffect(() => {
setState(id, initValue);
ref.current.firstRender = false;
return setupTriggers(id, trigger);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
const curValue = !firstRender ? getState<StateShape[K]>(id) : initValue;
return [
curValue as StateShape[K],
(value: StateShape[K]) => {
setState(id, value);
triggerRenderById(id);
}
];
};
export const watchGlobalState = <K extends StateKey>(id: K): StateShape[K] | undefined => {
const [_, trigger] = useState(id);
useEffect(() => setupTriggers(id, trigger), [id]);
return getState<StateShape[K]>(id);
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment