Panda Noir

JavaScript の限界を究めるブログでした。最近はいろんな分野を幅広めに書いてます。

Flux Utils のストアをいい感じに hooks で扱う

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 力ではこれが限界でした……