React/Reduxのスターターキットを公開している
React/Reduxビギナーのための、React/Reduxスターターキットを公開しているという記事。当初は最小限の機能で1ページのReduxアプリを作成するためのスターターキットを目指していたのだが、現在のSPA需用もありルーティングなどを追加した。
中身としては単純に、 react-create-app
コマンドで作成したReactアプリにReduxを組み込んだ形。 package.json
を見ると、追加したパッケージは基本的なReact/Redux関連のパッケージとコード整形系。webpackなど多くの部分は react-scripts
に依存している。
- react
- react-dom
- react-redux
- react-router-dom
- react-scripts
- redux
- redux-logger
- redux-thunk
- eslint
- eslint-config-prettier
- eslint-plugin-import
- eslint-plugin-prettier
- eslint-plugin-react
- eslint-plugin-react-redux
- prettier
ディレクトリ構造
ActionやReducerは専用のディレクトリやファイルに分けるのではなく、依存し合うそれぞれを1つのモジュール単位として、1つのファイルで管理する手法を採用している (Ducks proposal
と呼ばれてる?) 。これを採用するため、ducks-modular-redux
を参考にした。
. ├── public # 静的ファイル ├── src # アプリのソースコード │ ├── index.js # main render │ ├── reducers.js # combine Reducers │ ├── registerServiceWorker.js # Offline cache https://goo.gl/KwvDNy │ ├── shareComponents # share Components │ │ └── Header.js # page header │ ├── utils # convenient things │ │ ├── logo.svg # React icon │ │ ├── consts.js # your ENV │ │ └── injectStyle.js # you can use `@keyframes` │ └── app # application main sources │ ├── App.js # application routing │ ├── home # [home] `localhost:3000/` │ │ ├── index.js # [home] main Container │ │ └── Home.js # [home] main Component │ └── todo # [todo] `localhost:3000/todo` │ ├── index.js # [todo] main Container │ ├── Home.js # [todo] main Component │ ├── components # [todo] Components │ ├── containers # [todo] Container Components │ └── modules # [todo] main action logic files (include in `Action`, `Reducer`, `Action Creator`) │ ├── reducers.js # [todo] combine Reducers │ ├── todos.js # [todo] todo module │ └── todos.spec.js # [todo] todo module unit test └── LICENSE # License is MIT
ducks-modular-redux
では、依存するそれぞれのAction, Reducer, Action Creatorを1つのモジュールとして1つのファイルにまとめる手法を提案している。
よくある、ActionやReducerをそれぞれ専用のディレクトリやファイルとして/reducer/index.js
や/action.js
で管理されるパターンは、機能 (Action, Reducer) の追加が非常に煩わしい。たしかにうまく管理はできるのだが、実際にプログラミングしてアプリを作る場合、この面倒くささは未経験の想像する面倒くささを凌駕する。
このプロジェクトで採用しているプロジェクト構造は、全ての機能はモジュール単位で分けているため幾分マシだ。機能を追加したい場合、必要な分モジュールを追加するだけで良い。機能が大きくなると1ファイルが大きくなってしまうデメリットはあるが、可読性が失われることはほとんどないし、ファイル移動が必要ないというメリットがある。
// Actions const LOAD = 'my-app/widgets/LOAD'; // Reducer export default function reducer(state = {}, action = {}) { switch (action.type) { default: return state; } } // Action Creators export function loadWidgets() { return { type: LOAD }; }