reactを使ったアプリ開発の流れ

## reactを使ったアプリ開発

react.jsはviewの部分
データ管理にfluxフレームワークを導入が必要です

今回はreduxを利用したアプリ開発をベースに気をつける点などを説明します

---

## componentとは

componentはUIを独立した再利用可能な部分に分割したものです

reactはcomponentを組み合わせてページを構成します

```
class ButtonComponent extends Component {
  render() {
    return (
      <button>
        ボタン
      </button>
    );
  }
}
```

---

## props

componentでどのようなデータ描画するかは呼び出し元からpropsというデータをもらい描画します

```
  render() {
    return (
      <button
        onClick={this.props.onClick}
      >
        {this.props.buttonName}
      </button>
    );
  }
```

---

## bind問題

ReactをES6で書いた場合に、イベントハンドラでthisがundefinedとなりメソッドが実行できないという問題

参考
http://qiita.com/konojunya/items/fc0cfa6a56821e709065

私のプロジェクトではstage-0でメソッド定義しています

```

onClick = (e) => {
  this.props.onClick(e.target.dataset.key)
}

render() {
  return (
    <button
      deta-key="test"
      onClick={this.props.onClick}
    >
      {this.props.buttonName
    </button>
  );
}

```

arrow関数で書いていたこともありますがrenderをシンプルにしたい
renderの度にfunctionが生成されるのも無駄だよね
ということから移行しました

---

## propsのobjectの一部を書き換えたい

reactではprops/stateはimmutableなobjectとして扱います

勝手に上書きすると他の部分のrenderなどが勝手に変わる、意図したタイミングでレンダーされない
などのも問題が発生します

駄目な例

```
static propTypes= {
  item: React.PropTypes.shape({
    name: React.PropTypes.string,
    color: React.PropTypes.string,
  })
};

render() {
  this.props.item.color = '#000';
  return (
    <button
      style={{color: this.props.item.color}}
      deta-key="test"
    >
      {this.props.item.name}
    </button>
  );
}

```

immutableな変更の例

```
  const assigned = _.assign({}. this.props.item, {color: '#000'}})
```

```
  const updated = icepick.setIn(this.props.item, ['color'], '#000');

```

---

## state

componentの状態に応じてrenderを変えたい場合、stateを使って管理できます

が、componentはstateを持たず、propsのデータを描画するviewに専念することで
componentとしての役割が明確になりテストもしやすくなります

---

## redux

fluxフレームワークの一つ

Single source of truth
アプリの状態をもつStoreはただ1つ。

state is read-only
状態を変更するには必ずActionを発行しなければならない。

Changes are made with pure functions
Actionにより状態をどう変更させるかはReducerが行なう。

状態管理やレンダリングをきれいに分割できるのがメリット

---

## presentation componenntとcontainer component

reduxでは描画に特化させたcomponentをpresentation componentとよび
presentation componenntとstoreを結びつけるためにcontainer componentという
概念を用いてデータの管理を区別します

以下 presentation component -> component
container component -> container
としています

---

## container

componentにデータやコールバックを渡すcomponent

mapStateToPropsでstateから利用する値だけをとってpropsにセットします


```
onClickButton(key) {
  this.context.store.dispatch(action());
},

render() {
  return (
    <PageComponent>
      <ButtonComponent
        name: this.props.item.name,
        color: this.props.item.color,
        onClick={this.onClickButton}
      />
    </PageComponent>
  );
}

const mapStateToProps = (state: Object, ownProps: Object) => {
  return {
    name: state.name,
    color: state.color,
  };
};

export default connect(
  mapStateToProps
)(MainPageContainer);
```

---

## action

actionはアプリケーションからの情報をstoreへ送る為のオブジェクト

actionはtypeを必ず持ちます

```
const SHOW_DIALOG = 'SHOW_DIALOG';

function showDialog() {
  return {
    type: SHOW_DIALOG,
    dialogProps: {
      show: true,
      title: 'New Dialog',
    },
  };
}
```

---

## reducer

actionが起こった結果、どのようにstateが変化するかを対応するのがreducer

```
const initialState = {};
function reducer(state = initialState, action) {
  switch (action.type) {
  case SHOW_DIALOG:
    return _.assing({}, state, action.dialogProps);
  default:
    return state;
  }
}

```

reducerは分割してconbineReducerで結合したりするとreducerの管理がしやすくなります

```
export function createRootReducer(): Function {
  const reducers = {
    dialog: reduceDialog,
    button: reduceButton,
  };
  return reduceReducers(
    combineReducers(reducers),
    (state: Object = {}, action: Object) => {
      return {
        ...state,
      };
    }
  );
}



```

create-reducerを実装するとswitch文からも開放されて記述を減らせるのでおすすめ

```
export const reduceShowDialog = createReducer([], {
  [ActionTypes.SHOW_DIALOG](state, action) {
    return _.assing({}, state, action.dialogProps);
  }
})
```

http://redux.js.org/docs/recipes/ReducingBoilerplate.html#generating-reducers


---

## reduxの非同期処理

- redux-thunk
　- promiseを使った非同期処理

- redux-sage
　- generatorを使った非同期処理

redux-thunkではactionCreaterが肥大化していけどpromiseでゴリゴリっとかけるので楽ではある
一方、redux-sagaはgeneratorが必要でpolyfil入れたり多くの人に学習コストがかかったりするのけど
action周りはすっきりかけるとは思います

---

## style

inline styleかcssか

inline styleは物理的にstyleとhtmlが近いので修正は楽だけど、デザイナーが用意したcss等を
ちょっと修正したりする必要がでてきます

最近はpostCSSを使いlocal使って名前の重複を防ぎ、componentの中で使うclass名をシンプルなものにし、cssをそのまま使えるようにしています


---

## デバッグ

- react developer tools

chromeのdevtoolでcomponentがわかるようになります

- redux-devtools

こちらもchromeの拡張。stateの変化や状態をみることができます

---

## テスト

componentをシンプルにしておくとテストが楽になります

react-addons-test-utilsを使い
componentに任意のpropsを渡し、期待したnodeが生成されているかを判定するというテストができます

```
const props = {
  name: 'test',
  color: '#000'
};

const component = TestUtils.renderIntoDocument(
  <ButtonComponent
    {...props}
  />
);
const node = ReactDOM.findDOMNode(component);
assert(node.children.length === 1);
```

actionはredux-mock-storeを使ったりします



---