LoginSignup
2
3

More than 5 years have passed since last update.

ReduxなしでReduxっぽいことをやるのを快適にするためのライブラリを作った

Posted at

概要

mizchiさんの実践:React HooksなどにあるようにuseReduceruseContextをつかうことでReduxなしでReduxみたいなことができます。

小さな個人開発ではよく使えそうなテクニックだと思ったので、快適にそれを行うためのライブラリ、reducer-context-hookを勉強がてら作ってみました。

APIはfacebookincubator/redux-react-hookパクり参考にしました。

リポジトリ: https://github.com/sosukesuzuki/reducer-context-hook

API

create()

exportされているのはcreateという関数だけです。StoreContextProvidruseDispatchuseMappedStateを持つオブジェクトを返す関数です。引数はありませんが、型引数としてStateとActionの型を渡します(デフォルトだとany)。返り値のオブジェクトに含まれる3つをそのままexportせずにcreateをexportさせたのは単純に型引数を渡したかったという理由です。

import create from "reducer-context-hook";

const { StoreContextProvider, useDispatch, useMappedState } = create<
  State,
  Action
>();

StoreContextProvider

createの返り値のうちの1つです。propsとしてreducerと初期ステートを受け取ります。内部的にはそのままContextオブジェクトのProviderになっているのでコンポーネントツリーのルートあたりで囲んであげましょう。

function reducer(state: State, action: Action): State {
  switch (action.type) {
    case "increment":
      return { count: state.count + 1 };
    case "decrement":
      return { count: state.count - 1 };
    case "reset":
      return { count: 0 };
    default:
      throw new Error();
  }
}

const initialState: State = {
  count: 0
};

function App() {
  return (
    <StoreContextProvider reducer={reducer} initialState={initialState}>
      <App />
    </StoreContextProvider>
  );
}

useDispatch()

とてもシンプルなHookで、dispatchを返します。Actionを作って使いましょう。あと、Reduxを使わないといいましたが、ReduxのbindActionCreatorsはここで使えますね。(同様にcombineReducersもreducer定義で使えそう)

function Increment() {
  const dispatch = useDispatch();
  const increment = React.useCallback(
    () => dispatch({ type: "increment" }),
    []
  );
  return <button onClick={increment}>+</button>;
}

useMappedState(mapState, memoizationArray)

react-reduxで言うところのconnect(State限定)にあたります。Stateを引数にとってほしい値を返す関数(mapState関数)と、メモ化のためのキーを配列として引数にとります。内部ではuseCallbackを使ってメモ化しています。

function Counter() {
  const { count } = useMappedState(
    state => ({
      count: state.count
    }),
    []
  );
  return <p>{count}</p>;
}

感想

あ、まだnpmにpublishしてません。テスト書き終わったらpublishします。

Custom Hooksを書くのってとても楽しいです。これからも色々書いていきたいと思います。

2
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
3