【Part3】はじめてのReact勉強メモ

# はじめに

[前回](https://qiita.com/Grebinskij/items/025014e33e760a58ff60)の続きです。

公式チュートリアルの[Components and Props
](https://reactjs.org/docs/components-and-props.html)からやっていきます。

業務時間中にちまちま書いているんですが、なんとかモチベーションを落とさずに継続できています・・・！

# やってみる

## Components and Props

`Vue.js`でもやるコンポーネント分割と、コンポーネント間のデータの受け渡しのあたりの話ですね。
Part1でも若干触れましたが、基本的に`class`で定義するようです。`babel`を使わない場合は`funtion`で定義してもいいそうですが、`class`の方が色々と都合が良いとのこと。

こんな感じで使うんですね。コンポーネントを埋め込む際は`<Welcome>`のように先頭を大文字にするのがお作法のようです。

```JavaScript
class Welcome extends React.Component {
  render() {
    return <h1>Hello, {this.props.name}</h1>;
  }
}

class App extends extends React.Component {
  render() {
    return (
      <div>
        <Welcome name="Tanaka" />
        <Welcome name="Sato" />
      </div>
    )
  }
}

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

他には1コンポーネントが複雑化した際の分割方法が書かれてありましたが、`Vue`と同じような感じですね。

また、受け渡される`props`はreadonlyだとのことです。これも`Vue.js`では親のコンポーネントの値を変更するのは推奨されていませんでしたし、一緒ですね。

## State and Lifecycle

これまでは`ReactDOM.render()`によって描画を更新する方法しか知りませんでしたが、この章ではそれ以外の方法を教えてくれるそうです。

時計のコンポーネントを作るとしたら、これまでの知見だけでは

```JavaScript
function Clock(props) {
  return (
    <div>
      <h1>Hello, world!</h1>
      <h2>It is {props.date.toLocaleTimeString()}.</h2>
    </div>
  );
}

function tick() {
  ReactDOM.render(
    <Clock date={new Date()} />,
    document.getElementById('root')
  );
}

setInterval(tick, 1000);
```

こんな感じになりますが、これだと毎回`ReactDOM.render()`でアプリ全体の描画を更新することになってしまいます。
本当は`Clock`の内部で時刻を勝手に更新していくような作りにしたい・・・。

そこで、`state`をコンポーネントに定義しましょう。`Vue`で言うところの`data`ですね。
`state`を使うとこんな感じにかけるそうです。

DOMの定義部分では`this.state`でコンポーネントの`state`内の値を見にいって、`constructor`内で渡された`props`を`state`に保存するような動作にしています。

`Vue`で言い換えると`constructor()`が`created()`で`state`が`data`のイメージですね。

```JavaScript
class Clock extends React.Component {
  constructor(props) {
    super(props);
    this.state = {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')
);
```

続いて、時刻を更新する処理を作ります。`Vue`だと`mounted`で`setInterval`を入れて`beforeDestroy`で`clearInterval`するイメージですかね。

こんな感じにかけるそうです。想像通りですね。一度`constructor`で`state`を定義すれば、クラスにプロパティを足したりするのは自由らしいです。以下の例では`timerID`を後から追加していますね。

`state`の更新は`setState`を使う必要があるそうです。。`Vue`だと`methods`の中にコンポーネント内関数を定義していましたが、`react`だと`tick()`を定義しているようにクラス内に自由に定義して良さそうですね。もちろん`React.Component`の関数をオーバーライドしないように注意しなければいけ無さそうですが。

処理が呼ばれる順番はコメントに書きました。

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

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

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

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

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

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

`state`を変更する際は`setState()`を使う必要がありますが、`state`や`props`は非同期で更新されるので以下のように書く必要があると。

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

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

`setState`はシャローマージ?なので、既存のプロパティを壊さず一部を置換したりできると。

こんな感じに書いても、`this.setState({comments})`で`state.posts`が消えることは無いと説明しています。

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

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

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

残りの部分は、`state`がコンポーネント内にカプセル化していて、`props`は常に子コンポーネントに流れる単方向データフローであると説明しています。この辺りも`Vue`と同じですね。

# 終わりに

今回はコンポーネントとライフサイクルを学びましたが、なんとなく`React`でアプリを作る道筋が見えてきました。基本的な概念は`Vue`と変わらないですし、意外とすんなり受け入れられそうですね。次回は`Handling Events`からやっていきます。