react/fluxでpropsのバケツリレーを避ける

reactにfluxを採用してアプリケーションを設計していると、親->子->孫コンポーネントへpropsのバケツリレーになってしまう事がありました。
そもそもイケてない設計が悪いのですが、reactバケツリレーつらいという声を聞くことも多かったし、自分も辛いと思っていたところ[助言をいただいて](https://twitter.com/trapple/status/603520995295637504)解決法が見えてきたのでまとめてみます。



## propsバケツリレー

まず、バケツリレーを再現してみます。

### DOM構造

おおまかに`div[class="app"]`(親), `div[class="group"]`(子）, `div[class="item"]`(孫)というツリー構造になってます。

```html
<div class="app"><!--親-->
	<div class="group"><!--子-->
		<h2>1番目のグループ</h2>
		<p class="count">13</p>
		<div class="items">
			<div class="item"><!--孫-->
				...
			</div>
			<div class="item"><!--孫-->
				...
			</div>
			...
		</div>
	</div>
	<div class="group"><!--子-->
		<h2>2番目のグループ</h2>
		<p class="count">5</p>
		<div class="items">
			<div class="item"><!--孫-->
				...
			</div>
			<div class="item"><!--孫-->
				...
			</div>
			...
		</div>
	</div>
	...
</div>

```

で、これをComponent化するとそのまま`<App />`, `<Group />`, `<Item />`みたいに分けることができるんじゃないかと考えます。

### Storeが保持するデータ構造

Storeが保持するデータ構造も同じで複数のgroup(子)にぶら下がるitem(孫)達という感じです。


```js
{
	"group-1": [{item1-1}, {item1-2}, {item1-3}, ...],
	"group-2": [{item2-1}, {item2-2}, {item2-3}, ...],
	...
}
```

### App(RootComponent)

実際のComponentはどうなるかというと、
AppはStoreをsubscribeするRootComponentとして実装されこんな感じ。

```js
var Group = require("./Group.jsx");
var App = React.createClass({
	getInitialState(){
		return {
			groups: Store.getAll()
		}
	},
	render(){
		var groups = Object.keys(this.state.groups).map((key) => {
			return <Group items={this.state.group[key]} title={key} />;
		});
		return (
			<div className="app">
				{groups}
			</div>
		);
	},
	...
});
```

### Group

GroupからItemへ値のリレー

```js
var Item = require("./Item.jsx");
var Group = React.createClass({
	render(){
		var items = this.props.items.map((item) => {
			return <Item {...item} />
		});
		return (
			<div className="child">
				<h2>{this.props.title}</h2>
				<p className="count">{this.props.items.length}</p>
				<div className="items">
					{items}
				</div>
			</div>
		);
	}
});
```

このようにDOM構造と同じだけReactComponentも入れ子していってしまうと、
propsのバケツリレーで面倒なだけでなく、Itemへ渡したい値は必ずGroupを通らねばならず、GroupはItemの設計に依存してしまいます。
これではGroupはテストも作りにくく変更にも弱いですね。

## propsのバケツリレーを無くすために

### 依存を無くす

子孫間の依存を無くすために、`<Item />`に渡すpropsを`<App />`から直接渡す形に変更します。

```js
var Group = require("./Group.jsx");
var Item = require("./Item.jsx");
var App = React.createClass({
	getInitialState(){
		return {
			groups: Store.getAll()
		}
	},
	render(){
		return (
			<div className="app">
				{this.renderGroups()}
			</div>
		);
	},
	renderGroups(){
		var groups = Object.keys(this.state.groups);
		return groups.map((key) => {
			return (
				<Group count={groups[key].items.length} title={key}>
					{this.renderItems(key)}
				</Group>
			);
		});
	},
	renderItems(key){
		var items = this.state.groups[key];
		return items.map((item) => {
			return <Item {...item} />;
		});
	},
	...
});
```

```js
var Group = React.createClass({
	render(){
		return (
			<div className="group">
				<h2>{this.props.title}</h2>
				<p className="count">{this.props.count}</p>
				<div className="items">
					{this.props.children}
				</div>
			</div>
		);
	}
});
```

変更のポイントは`<Group>{items}</Group>`という形で`<Item />`（の集合）を直接Componentとして渡すことです。
このように配置された場合、itemsは`<Group />`の`this.props.children`に入るので、そのまま任意の場所に流し込めばよいでしょう。
この変更により`<Group />`に渡されるComponentは何の縛りもなくなり、ただ自分の管轄であるtitleとcountだけを受け取ればいい形になりました。

当たり前にやってる人にはなんの驚きもないとおもいますが、自分はそもそもpropsにComponentを渡すという発想が希薄だったので、これは目から鱗でした。アドバイスを下さった @axross_ さんに感謝m(_ _)m

もっとこうしたほうがいいよとかありましたら、是非コメントをください。

## 参考

[コンポーネント指向による、Reactのベストプラクティスとバッドプラクティス](http://www.slideshare.net/axross/react-48651340)