2016年8月29日月曜日

React-Reduxを使った開発でのディレクトリ構成をどうしたらいいのか的なことから、こうやって組んだらいいんじゃないか的なお話

  • このエントリーをはてなブックマークに追加

React-Reduxを使うとすっごく便利なわけで。
ただ問題となるのがディレクトリ構成をどうしようかと。
もちろん公式での書き方とかあったりするけれども、github上で他の人がアップしているexampleとか見ると若干違うような気がするとか。

人それぞれいろんな書き方があるのはわかるけれども、なんていうか気持ち悪いというかなんというか。
ってことで今回はどこらへんに注目しつつ、自分としてはこうやって構成した方が気持ちいいんじゃないかというお話をば。

■公式でのそもそものcontainerとcomponentの違い

この図のような感じ。リンクはこちら
Presentational Components(俗にいうcomponent)はpropsとしてデータを渡される
Container Components(俗にいうcontainer)はactionをdispatchしたりなんていうか色々とやる

事例も色々と載っているわけで、基本的にはcontainerではjsxを書かずにdispatchしたりしている


react-redux-universal-hot-exampleでの書き方

srcのcomponentを見るとわかるけど、buttonだとかbarだとか細かいパーツを置いているイメージ
一見間違ってはいない気がするけど、ものによってはbuttonだとかのcomponent内でactionをdispatchしているので違うと思う。


react-router-reduxでの書き方

こっちはexample/basicを見るとわかるけど、containerは置かずにcomponentのみで構成している
Home.jsはactionをdispatchしているが、他のものは何もせずっていう感じの書き方。
これはこれでありだと思うけど、規模が小さいから成り立つではあろうと思うから、規模が大きくなるにつれ管理が難しそうな気がする


■自分が考えるcomponentとcontainerの構成

自分としてはこうしたいなぁという点が下記になる。
・componentとcontainerっていうのは明確的にわけておきたい。
・containerでjsxを書くとなるとcomponentとの違いは?となったりしてなんとなく気持ち悪い。
・大規模になった場合に呼び出し元をいちいちcomponentからcontainerに書き換えるとかしたくない。

という点を考えると下記のような感じで構成をしていきたいと思う。
ちなみにこれは一部抜粋なので、作ったサンプルはこちらのgithubから。

app.js
components/
 - header/
    - header.js
    - header.scss
    - index.js
 - footer/
    - footer.js
    - footer.scss
    - index.js
 - button/
    - primaryButton.js
    - successButton.js
    - warningButton.js
    - dangerButton.js
    - index.js
 - foobar/
    - foobar.js
    - foobar.scss
    - index.js
 - welcome/
    - welcome.js
    - welcome.scss
    - index.js
containers/
 - header/
    - header.js
    - index.js
 - foobar/
    - foobar.js
    - index.js
 - welcome/
    - welcome.js
    - index.js
// actionをdispatchしたい場合はcontainerを呼び出し
import Header from '../../containers/header'

// actionをdispatchしない場合はcomponentを呼び出し
//import Header from './header'

export default Header
import Header from './header'

export default Header
import React from "react";
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux'

/* actions */
import * as hoge from '../actions/hoge'

//componentからheaderを呼び出してdispatch
/* components */
import Header from '../../components/header';

/* state to props */
const mapStateToProps = (state, ownProps) => {
  return {...state}
}

/* dispatch to props */
const mapDispatchToProps = (dispatch) => {
  return bindActionCreators({
    ...hoge,
  },dispatch);
}

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(Header)

基本的にcontainerからimportはしないで、componentからimportをするようにする。
その際にディレクトリ内にindex.jsを入れておくことで、ここでimportとexportを制御することができるので、
containerを使いたい場合はその中でcontainerをimportするようにする。
そうすることでcomponentじゃなくてcontainerを暗黙的にimportできるっていう感じ。


ってな感じでいけばcontainerでjsxを書くこともないし、stateとactionをdispatchするだけでよい。
またcomponentからcontainerを呼び出すことでcontainerとcomponentのだしわけをしないですむ。
ただファイル数がその分増えるのは面倒だけど、わかりやすさとしてはいいんじゃないかと。

という感じでReact-Reduxの場合はこういう構成でいこうかと。
みんなそれぞれの書き方をしてるし、そういう場合はより複数人で組むとかそういうときにわかりづらいとかはなくしたいわけで。

というかフロントエンドでみた、情報系ブログとはてブの地獄メカニズムというような状況ってかなりあるよなぁっていうイメージ。
reactなどで情報を検索してもみんな書いてることは触りみたいなことばかりでほぼ同じ。
深く踏み込んだ話もないし、勉強会に出てもみんな同じようなこと言ってるし、会社で使ってるならばそのリンクまずは教えてくれよとか思う。
実際に使ってるとなるとつまづくポイントもいくつかあるわけで。
けどそんなことを言ってても意味がないので、とりあえずReactをがんばりましょうという感じ的なみたいな。

Adsense