https://github.com/Fieldscope/flux-hooks を参考にしつつ、型をつけたり型推論が効きやすいように調整したりしてます。
export const useFluxStore = < TStore extends ReduceStore<TState, unknown>, TState = ReturnType<TStore['getState']> >( store: TStore, reducer: (store: TStore) => TState = store => store.getState(), deps: unknown[] = [] ): TState => { const [out, dispatch] = useReducer( (_, store) => reducer(store), reducer(store) ); useMemo(() => { dispatch(store); }, deps); useEffect(() => { const token = store.addListener(() => dispatch(store)); dispatch(store); return () => token.remove(); }, [store]); return out; };
使う方は非常にカンタンです。これだけ。
const state = useFluxStore(Store);
注意: destructuring してはいけない
型推論がうまく働かなくなるので destructuring はしないでください。
const {foo: hoge, bar: fuga} = useFluxStore(Store); // hoge と fuga はどちらも any になってしまう
一旦変数に格納した後であれば destructuring しても問題ありません。
const store = useFluxStore(Store); const {foo: hoge, bar: fuga} = store; // これなら OK const hoge = useFluxStore(Store).foo; // これも問題なし
僕の TS 力ではこれが限界でした……