コンポーネント指向でreact-reduxで画面を作るための考え方

# 概要
コンポーネント指向について、分かったような気になって実際に作ってみたら色々ごちゃごちゃしてしまったのだが、改めて考えを整理したら少し上手くいくようになった。

上手くいってなかった時と、上手くいった今の、考え方のdiffを稚拙ながら整理したので以下に紹介する。

react-reduxを使って、よくある一覧画面を作ることを想定しながら、紹介する

# 前提
- webpackなどを使ったjs・jsxのビルドやトランスパイルができている前提

# 考え方１・コンポーネントが最初
何はともあれ、コンポーネントから作る。

例えばこんな感じの画面を作ることを考える。（店舗一覧画面）
<img width="400" alt="スクリーンショット 2018-12-17 11.33.20.png" src="https://qiita-image-store.s3.amazonaws.com/0/71390/79b3fddb-9cd9-5a64-3685-e04d9c7a0c58.png">

ロード中はこうする
![スクリーンショット 2018-12-17 12.12.01.png](https://qiita-image-store.s3.amazonaws.com/0/71390/236771a0-b793-6309-8016-7f556d9d1a4f.png)



画面の中で使うであろうコンポーネントをまず列挙する
多分こんな感じ

![スクリーンショット 2018-12-17 11.43.49.png](https://qiita-image-store.s3.amazonaws.com/0/71390/2656acb8-f310-ee80-691f-dfe62f06a0cc.png)

各コンポーネントを実装する。どんなpropsがあればいいかを考えながら実装する。
既存の世にあるコンポーネントも適宜使う（ここでは most poularである [Material-UI](https://material-ui.com/) を使う。その場合も適宜ラップしたりする。)
多分こんな感じ。括弧内は必要そうなpropsと処理

```
- Atoms
    - TextField (Enter押した時のハンドラ、placeholder、など)
    - IconButton (アイコンの種類、クリックした時のハンドラ、など）
    - Button (クリックした時のハンドラ、など)
   
- Molecules
    - SearchBox (ボタンクリックやEnterを押した時のハンドラ/ハンドラのトリガ)
    
- Organisms
    - BranchCard (店舗ID、店舗名、店舗住所、など)
    - BranchList (店舗情報リスト)
    - Pagination (現在の表示数、合計数、次があるか、前があるか、など/前、次を押した時のハンドラ）
    - Loading (特になし)
    
- Templates
    - ListPageTemplate (ヘッダ部分のコンポーネント、リスト部分のコンポーネント、ページナビ部分のコンポーネント、ローディング表示かどうか)
    
- Pages
    - BranchesListPage (ajaxで取得した店舗リスト、データ取得中かどうか、現在の検索条件/マウント時にデータ取得、ページ移動した時にデータ取得・URL変更、ListPageTemplateに各コンポーネントを渡してrender、など)
```

AtomsやMoleculesなどは特に、汎用性が高くなるように作る。例えば AtomsやMoleculesなどの部品で `margin`を定義してしまうと、他で使う時にまた調整が必要になってしまったりするので、AtomsやMoleculesの部品の`margin`などは親側のコンポーネントで設定するのが定跡。

## atomic designについて
以下が分かりやすい

SlideShare
[UI 開発をアジャイルに行うための Atomic Design](https://www.slideshare.net/ygoto3q/atomic-design-for-agile-ui-development-100961721)

書籍
[Atomic Design ～堅牢で使いやすいUIを効率良く設計する](https://www.amazon.co.jp/gp/product/477419705X/ref=s9_acsd_simh_hd_bw_b245A_c_x_1_w?pf_rd_m=AN1VRQENFRJN5&pf_rd_s=merchandised-search-4&pf_rd_r=C1FKFZX7860EXZCXYD9D&pf_rd_t=101&pf_rd_p=64bdd22c-2d07-5f3a-9250-28b2f65d18d8&pf_rd_i=492352)


# 考え方2・コンポーネントが必要とするpropsを元にReducerを実装する
コンポーネントを考えてからreducerを実装する。reducerを先に考えてコンポーネントをそれに合わせるように実装するのではない。
先に列挙したコンポーネントのなかで、reducerが必要なものは`BranchListPage`。他は親からpropsを渡す。

例えばこんな感じのreducerになる

```javascript
import { LOCATION_CHANGE } from 'react-router-redux';
import {
  REQUEST_BRANCHES,
  RECEIVE_BRANCHES,
  REQUEST_BRANCHES_FAILURE,
} from '~/constants/actionTypes';

const initialState = {
  loading: false,   // ロード中かどうか。Loadingを描画するかどうかの判定で使う
  search: '',       // 検索ワード。表示したり、TextFieldにあらかじめ表示しておくなら使う
  total: 0,         // データの合計数。表示するので使う
  page: 0,          // 現在のページ。表示したり、次や前へを押せるか、また押した時に、どうリクエストを送るのかに使う
  rowsPerPage: 5,   // １ページあたりの件数。表示したり、次や前へを押せるか、また押した時に、どうリクエストを送るのかに使う
  offset: 0,        // 現在何件目からを表示しているのか。表示したり現在のページの計算に使う
  items: [],        // 表示するデータ。表示するのに使う
};

export default function branchesList(state = initialState, action) {
  switch (action.type) {
    case LOCATION_CHANGE: {
      // URLによってpropsが変わるならここに処理を書く。ここでは省略
    }
    case REQUEST_BRANCHES:
      return {
        ...state,
        loading: true,
      };
    case RECEIVE_BRANCHES: {
      const {
        orders: items,
        offset,
        total,
        limit,
        search,
      } = action.data;
      const page = Math.floor(offset / state.rowsPerPage, 10);
      return {
        ...state,
        loading: false,
        search,
        items,
        offset,
        total,
        page,
      };
    }
    case REQUEST_BRANCHES_FAILURE:
      return {
        ...state,
        loading: false,
      };
    default:
      return state;
  }
}

```

あとはactionsやstyleを作って終わり。

# 考え方3:何か変更があった時も、コンポーネントを優先して考える
何か変更があった時も、コンポーネントを優先して考える。reducerやactionありきではなく、コンポーネントありきである。

例えば、この一覧画面で、別の項目を増やしたいだの、１ページあたりに表示できる件数を変更できるUIが欲しいだの、検索条件をもっと増やしたい、ソートしたい、ログインユーザをヘッダに出したい、などなど、どんな変更でも、それがコンポーネントにどう影響するかを考える。

コンポーネントが表示する内容がどうなるか、コンポーネントが表示する内容を決めるためにpropsが増えるとか、そのためには新たなactionが必要、新たなreducerの実装が必要、など、そういう順番で考える。

storybookも最初から作った方が、コンポーネントが綺麗に作れているかが分かるのでいい。
[storybook](https://storybook.js.org/)

# まとめ
とにかくコンポーネントが先、そのほかのことは後。というふうに、考えればスッキリした設計になる。