Redux の store や connect を偽装してみた

# はじめに

お友達のフリーランスエンジニアが、RubyエンジニアからJSエンジニアReact案件に移行できたと聞いた記念で、redux を学んでみます。

# 元サンプル

Redux サンプルとしてシンプルなTODOアプリを動かします。

CodeSandbox というWebで動作する。とてもわかりやすいTODOサンプルを作っていただいているページがありましたので、こちらでReact-Reduxを動かします。

FN2004004 | React + Redux入門 07: React ReduxのフックuseDispatch()とuseSelector()を使う | HTML5 : テクニカルノート
http://www.fumiononaka.com/Business/html5/FN2004004.html

react-redux-todos-02 - CodeSandbox
https://codesandbox.io/s/react-redux-todos-02-tpvcw?from-embed

ここからFork して動くサンプルを作っていきます。

# 初期状態

単なるForkコピーです。

react-redux-todos_1 - CodeSandbox
https://codesandbox.io/s/react-redux-todos1-mlowe

これを改良していきます。

# Action を削除

AddTodo.js からリンクしている、addTodo があるのでこれを消す。
これは簡単

react-redux-todos_2 - CodeSandbox
https://codesandbox.io/s/react-redux-todos2-jydzh?file=/src/index.js

# react だけで書き直す

Reduxは、store オブジェクトを下位オブジェクト全てに伝搬するという Provider store の機能で成り立っていて
アプリケーション唯一の store を下位オブジェクトに配っているだけ。

アプリケーション唯一の state を下位に配るのと大差ない感じなのでそのように改良してみます。

ルートのindex.js から Provider store を削除して App.js で 単独の State をつくり、AddTodo に onAddTodo 関数を定義する

AddTodo.js 側は、いままで、配布されていた Store.dispatch を受け取るのをやめて 単に、onAddTodo をうけとって追加するようにする

Todo コンポーネントも暗黙でstoreをProviderを使って渡されていた todos を自前で渡すようにする

Connectという仕組みも削除する。これで、reducer フォルダの中身も削除できる

react-redux-todos_3 - CodeSandbox
https://codesandbox.io/s/react-redux-todos3-lxfkt?file=/src/components/App.js

Redux をつかったアプリケーションよりもかなりシンプルで理解しやすい記述になった感じです。

# reduxを偽装してみる。

一番はじめの react-redux-todos_1 から、新たに作りなおします。

ルートのindex.js から Provider store を削除してApp.js で 単独の State をつくり、AddTodo に onAddTodo 関数を定義するのは同じ

AddTodo.js を改良なしに使うために上位からdispatch を渡すためにstore = { dispatch, todos } のオブジェクトをつくります。

これで、AddTodo.js と TodoList.js の connect を削除して、

dispatch の中で、message を受け取って、reducer/todos.js にわたすと

redux を排除したプロジェクトで同じ機能で動きます。

react-redux-todos_4 - CodeSandbox
https://codesandbox.io/s/react-redux-todos4-4sr5e

# Provider だけ取除いてみる

一番はじめの react-redux-todos_1 から、新たに作りなおします。

そもそも、Provider ってなんなのか、っていうと、バケツリレーって仕組みですね。

Provider抜きでう動かしてみます。

ルートのindex.js のProviderを消して、App.js で store 次々に渡しています。

react-redux-todos_5 - CodeSandbox
https://codesandbox.io/s/react-redux-todos5-umsyk?file=/src/index.js

元のサンプルはバケツリレーを隠蔽しようとして、Provider って仕組みを使っているのですが、実際のところ、バケツリレーのほうがデータの流れがみえてわかりやすいん。

Provider は状態変数をこっそり下位オブジェクトにわたす仕組みなので、コンポーネントの独立性が下がり、再利用性が下がり、他のところに移動させると動かない、という場合があるので、

Provider を使うと少し記述量は減るけど不可思議な挙動になってしまってコンポーネントの独立性が失われる仕組みなので

あまりおすすめしません。

わかりやすいコードを書きたいならバケツリレーで一つずつちゃんとオブジェクトを渡しましょう。

# バケツリレーをもう少し書きやすく

Reactのスプレッド構文を使うと、store の記載がいくらか減ります。

react-redux-todos_6 - CodeSandbox
https://codesandbox.io/s/react-redux-todos6-p3pq9?file=/src/components/App.js

# Store を偽装する

これらを踏まえて、

再度、react-redux-todos_1 からフォークして、storeを書き換えてみます。

store を、ルートのindex.js で置き換えて、

reducer/index.js の combineReducers 消したり
AddTodo.js と TodoList.js の connect を削除したりして引数の取り出しをしたりして、

いろいろあれやこれやしてみて、reduxコードを活かしながらstore部分をつくりこんで

他の部分は 最小限の修正で redux をプロジェクトから除外して、store を偽装してみました。

react-redux-todos_7 - CodeSandbox
https://codesandbox.io/s/react-redux-todos7-e2msk?file=/src/index.js

# もう少し偽装Storeを改良する

store 内に todo というプロパティが埋め込まれているので、ここを改良します。

react-redux-todos_8 - CodeSandbox
https://codesandbox.io/s/react-redux-todos8-xsojj?file=/src/index.js

# さらに改良して、connectも作り込む

react-redux-todos_9 - CodeSandbox
https://codesandbox.io/s/react-redux-todos9-shpc9?file=/src/components/AddTodo.js

これで、react-reduxの connect や store を自前で実装できていると思います。

# 終わり
以上、サンプルでした。