[Get started]から始めるReact開発：その4(State and Lifecycle②

引き続き[React](https://facebook.github.io/react/docs/state-and-lifecycle.html)

[[Get started]から始めるReact開発：その1](http://qiita.com/t-katsura/items/6c3a92583b8a738e2921)
[[Get started]から始めるReact開発：その2:Rendering Elements](http://qiita.com/t-katsura/items/43ac2e758fd53a8a9ffa)
[[Get started]から始めるReact開発：その3:Components and Props](http://qiita.com/t-katsura/items/d3c320a0b68cee7c9d77)
[[Get started]から始めるReact開発：その4(State and Lifecycle①](http://qiita.com/t-katsura/items/7b8e4889fe73e4d3245d)
[[Get started]から始めるReact開発：その4(State and Lifecycle②](http://qiita.com/t-katsura/items/24a14ff763ac7738a036)
あまりに長かったので分割しました。

##Adding Lifecycle Methods to a Class(クラスにライフサイクルメソッドを加える

多くのコンポーネントを含むアプリケーションでは、コンポーネントが破棄される時に合わせてリソースの開放をすることが非常に重要です。
`Clock`は最初にDOMにレンダリングされるときに毎回タイマーを設定しなければいけません。これを`React`では`mounting`と呼びます。
また`Clock`によって作られたDOMが削除された時にタイマーをかいほうしなければいけません。これを`React`では`unmounting`と呼びます。
コンポーネントが`mounts`や`unmounts`する時に幾つかのコードを実行するための特別なメソッドを宣言できます。


```
class Clock extends React.Component {
  constructor(props) {
    super(props);
    this.state = {date: new Date()};
  }

  componentDidMount() {

  }

  componentWillUnmount() {

  }

  render() {
    return (
      <div>
        <h1>Hello, world!</h1>
        <h2>It is {this.state.date.toLocaleTimeString()}.</h2>
      </div>
    );
  }
}
```

これらのメソッドは`lifecycle hooks`と呼ばれています。

`componentDidMount()`フックはDMOMにコンポーネントがレンダリングされたあとに実行されます。これはタイマーをセットするのに最適です。

```
  componentDidMount() {
    this.timerID = setInterval(
      () => this.tick(),
      1000
    );
  }
```

`this`にtimerIDを保存する方法については注意してください。
`this.props`はリアクトによって設定され、`this.state`は特別な意味を持ちますが、視覚的なアウトプットに使用されないようなデータを保存する必要がある場合はクラスに手動で追加のフィールドを加えることは自由にできます。
`render()`でそのデータが使われない場合は、stateにはないほうがよいでしょう。

`componentWillUnmount()`ライフサイクルフックではタイマーを破棄します。

```
  componentWillUnmount() {
    clearInterval(this.timerID);
  }
```

最後に、毎秒実行するメソッドの`tick()`を実行します。

コンポーネントの`local state`の更新を調整するために`this.setState()`を使用します。

```
class Clock extends React.Component {
  constructor(props) {
    super(props);
    this.state = {date: new Date()};
  }

  componentDidMount() {
    this.timerID = setInterval(
      () => this.tick(),
      1000
    );
  }

  componentWillUnmount() {
    clearInterval(this.timerID);
  }

  tick() {
    this.setState({
      date: new Date()
    });
  }

  render() {
    return (
      <div>
        <h1>Hello, world!</h1>
        <h2>It is {this.state.date.toLocaleTimeString()}.</h2>
      </div>
    );
  }
}

ReactDOM.render(
  <Clock />,
  document.getElementById('root')
);
```

現在時計は毎秒刻みで動きます。

これらがどのように動いているのかということとメソッドが呼ばれる順番をおさらいしましょう。

1) `<Clock />`が`ReactDOM.render()`に渡された時、リアクトは`Clock`コンポーネントのコンストラクタを呼び出します。`Clock`は現在の時間を表示する必要があるため、現在の時間を含んだオブジェクトで`this.state`を初期化します。

2) Reactは`Clock`コンポーネントの`render()`メソッドを呼び出します。これは何を画面上に表示すべきかをReactに知らせています。Reactはアウトプットに合うようにDOMを更新します。

3) `Clock`アウトプットがDOMに入れられた時に、Reactは`componentDidMount()`を呼び出します。その中では、`Clock`コンポーネントが毎秒`tick()`を呼ぶためのタイマーの設定をブラウザに対して要求しています。

4) 毎秒`tick()`メソッドがブラウザから呼ばれます。その中では、`Clock`コンポーネントが現在の時間を含んだオブジェクトで`setState()`を呼び出すことでUI更新を調整します。`setState()`呼び出しに感謝をして、Reactは`state`に変更があることを知り、何が画面上に表示されるべきかを再度知るために`render()`メソッドを呼びます。この時、`render()`メソッドの中の`this.state.date`は異なりますし、描画されるアウトプットは更新された時間も含みます。ReactはそれによってDOMを更新します。

5) `Clock`コンポーネントがそのうちにDOMから削除された場合は、Reactは`componentWillUnmount()`を呼び出しタイマーをストップします。

##Using State Correctly

`setState()`について知るべきことが3つあります。

###Do Not Modify State Directly(Stateは直接変更できない

例えば、下記はコンポーネントでの再レンダリングができません。

```
// Wrong
this.state.comment = 'Hello';
```

代わりに`setState()`を使用します。

```
// Correct
this.setState({comment: 'Hello'});
```

`this.state`を割り当てることができるただひとつの場所はコンストラクタです。

###State Updates May Be Asynchronous(Stateはの更新は非同期に

Reactはパフォーマンスのために一つの更新の中で複数の`setState()`呼び出しをバッチできます。
`this.state`と`this.props`は非同期に更新されるので、次のStateを計算するためにそれらの値を使うべきではない。

例えば、下記コードはカウンターの更新に失敗する。

```
// Wrong
this.setState({
  counter: this.state.counter + this.props.increment,
});
```

これを修正するためにオブジェクトというよりは関数として受け入れる`setState()`の第二形式を利用します。
この関数は第一引数として前のstateを受け入れ、第二引数として更新が適用された時のpropsを受け入れます。

```
// Correct
this.setState((prevState, props) => ({
  counter: prevState.counter + props.increment
}));
```

上記はアロー関数を使用しましたが、通常の関数としても利用できます。

```
// Correct
this.setState(function(prevState, props) {
  return {
    counter: prevState.counter + props.increment
  };
});
```

###State Updates are Merged

Reactでは`setState()`を呼ぶ時は、現在のStateの中で渡されたオブジェクトをマージします。
例えば、Stateが独立した複数の変数を含んでいる場合

```
  constructor(props) {
    super(props);
    this.state = {
      posts: [],
      comments: []
    };
  }
```

別々の`setState()`呼び出しで個別にそれらを更新することができます。

```
  componentDidMount() {
    fetchPosts().then(response => {
      this.setState({
        posts: response.posts
      });
    });

    fetchComments().then(response => {
      this.setState({
        comments: response.comments
      });
    });
  }
```

マージが浅いので、`this.setState({comments})`は`this.state.posts`についてはそのまま残しますが、`this.state.comments`については完全に入れ替えます。

##The Data Flows Down

親でも子でもないコンポーネントは、コンポーネントがステートフルかステートレスかを知ることができますし、関数として定義されているかクラスとして定義されているかどうかを気にする必要はありません。
これが`State`がよくカプセル化もしくはローカルと呼ばれる理由です。それをセットしたものやそれ自身以外のコンポーネントからは利用できません。
A component may choose to pass its state down as props to its child components.（ちょっといみわからん、というかここからちょっと英語よくわかんなくなったのでほぼ機械翻訳）

```
<h2>It is {this.state.date.toLocaleTimeString()}.</h2>
```

これはまた、ユーザー定義コンポーネントとして働きます。

```
<FormattedDate date={this.state.date} />
```

`FormattedDate`コンポーネントは`date`をpropsで受け入れ、それが`Clock's state`や`Clock's props`もしくは手で入力されたものかどうかはしりません。

```
function FormattedDate(props) {
  return <h2>It is {props.date.toLocaleTimeString()}.</h2>;
}
```

[CodePenで確認](https://codepen.io/gaearon/pen/zKRqNB?editors=0010)

これは一般的に`top-down`もしくは`unidirectional`データフローと呼ばれています。全てのstateは常に特定のコンポーネントに所有され、そのstateから派生した全てのデータやUIはツリー内のコンポーネントの下にのみ影響を与えます。

滝のようなものを想像してください。それぞれのコンポーネントStateがそれぞれの水源に流れていくイメージです。

それぞれのコンポーネントは完全に独立しているようにみえるため、3つの`<Clock>`をレンダリングしたAppコンポーネントを作ることができます。

```
function App() {
  return (
    <div>
      <Clock />
      <Clock />
      <Clock />
    </div>
  );
}

ReactDOM.render(
  <App />,
  document.getElementById('root')
);
```

[CodePenで確認](https://codepen.io/gaearon/pen/vXdGmd?editors=0010)

それぞれの`clock`はタイマーのセットと更新を個別に行っています。
React Appｓでは、コンポーネントがステートフルかステートレスかどうかは時間とともに変わるかもしれないコンポーネントの詳細な実装を考える必要があります。ステートフルなコンポーネントの内側のステートレスコンポーネントを使うことができますし、その逆もまた可能です。