Reactの基礎を理解しよう

#目次
* [概要](#概要)
* [Reactの基本文法](#reactの基本文法)
* [JSX](#jsx)
* [Component](#component)
* [props](#props)
* [state](#state)
* [2種類のrender()](#2種類のrender)
* [まとめ](#まとめ)

#概要
この記事はReact初心者である私がReactの基礎についてまとめたもので、私のようにReactをこれから学習しようとしている人向けの内容となっています。
Reactとは何か、Reactの開発環境の構築方法については[別の記事](https://qiita.com/jima-r20/items/6a8ec87af37ab0193d02)にまとめてありますのでそちらを参考にしてみてください。
また私の記事は、より詳しい方が書いた記事等を参考にまとめていますので、さらに詳細に知りたい方は[参考資料](#参考資料)を見ることをおすすめします。

#Reactの基本文法
* Reactは**JavaScriptのライブラリ**
* 基本的な文法はJavaScriptベース
* **JSX**と呼ばれるJavaScriptの中に直接HTMLを記述できる技術がある
* アロー関数やclass構文などES6から実装された文法を取り入れている

React基本的な文法はこの辺りだと思います。

#JSX
JSXとは「[Reactの基本文法](#Reactの基本文法)」でも述べたように、JavaScriptのコード内で`<div>...</div>`というHTMLのような記述方法で記述できる技術です。

では実際の記述方法を見てみましょう。
最も簡単なJSXの例としては下記のような記述となります。

```react:src/App.js
const element = <h1 className="greeting">Hello, world.</h1>;
```

`element`に入っているタグ構文は文字列でもHTML要素でもなく、これがJSXです。

このように1つのファイル内でJavascriptとHTMLの記述方法を併用できるのか疑問に思う人もいるはずです。コンピュータ（ここではブラウザ）は賢いようでそうではないので本来であればJavaScript内に記述されたHTML構文を解釈することができません。

そこで登場するのがJavaScriptトランスパイラである**Babel**です。このBabelによって`React.createElement()`の形式つまりJavaScript形式に変換されます。Babelは他にもES2015などに対応していないブラウザに対して、対応できる形式に変換してくれる機能もあります。

以下がBabelによって変換された後の内容です。

```react:src/App.js
import React from 'react';

const element = React.createElement(
  'h1',
  {className: 'greeting'},
  'Hello, world.'
);
```
Babelに頼らず`React.createElement()`を使って直接記述することもできますが、JSXの方がわかりやすいし書きやすいですよね。

他にもJSXの記述方法にはいくつかのルールのようなものがあります。その中でも利用頻度の高いものは次の項目だと思います。

* 返す要素は１つにまとまった要素として記述する必要がある
* JSX内でJavaScriptを記載するときは{ }で囲む
* 関数の呼び出しもできる
* HTMLのclassはJSXではclassNameにする

```react:src/App.js
import React from 'react';

const name = '太郎';
const age = '10';
add(x, y){ return x + y; }

render() {
  return (
    <div>
      <h1 className="greeting">こんにちは</h1>
      <p>僕の名前は{name}です。{age}歳です。</p>
      <p>1 + 2 = {this.add(1, 2)}</p>
    </div>
  );
}
```
このような感じになります。
`return`で返している要素は`<div>`タグの中にまとまっていますので１つの要素と見ることができます。

１つの要素としてまとめる際に`<div>`タグを用いることで余計なDOM操作をすることになるので`<React.Fragment>`というものを利用した方がいいです。

```react:src/App.js
import React from 'react';

const name = '太郎';
const age = '10';
add(x, y){ return x + y; }

render() {
  return (
    <React.Fragment>
      <h1 className="greeting">こんにちは</h1>
      <p>僕の名前は{name}です。{age}歳です。</p>
      <p>1 + 2 = {this.add(1, 2)}</p>
    </React.Fragment>
  );
}
```

#Component
`Component`(コンポーネント)とは、Reactの最終的な出力であるJSXを構成するUI部品のことで、一度作成すれば何度でも再利用することができます。

例えばJSXで、

```react:src/App.js
import React from 'react';
import ReactDOM from 'react-dom';

ReactDOM.render(
  <React.Fragment>
    <div>
      <h1>Hello,World.</h1>
      <h2>Hi, everyone.</h2>
    </div>
    <div>
      <h1>Hello,World.</h1>
      <h2>Hi, everyone.</h2>
    </div>
  </React.Fragment>,
  document.getElementByID('root');
);
```
という`<div>...</div>`の中身が同じものが２つあったとき、何度も同じ構文を記述することはめんどくさいし効率が悪いですよね。
(`ReactDOM`などまだ紹介していないところもありますが今は気にしないでください。後ほど説明します。)

そんなときに登場するのが**コンポーネント**です。言葉で説明してもイメージがつきにくいと思うので実際に先ほどの例を書き換えてみましょう。

```react:src/App.js
import React, { Component } from 'react';

class Greeting extends Component {
  render() {
    return(
      <div>
        <h1>Hello, world.</h1>
        <h2>Hi, everyone.</h2>
      </div>
    );
  }
}

// ここ！！
ReactDOM.render(
  <React.Fragment>
    <Greeting />
    <Greeting />
  </React.Fragment>,
  document.getElementById('root')
);
```
このように記述できます。
今回はコンポーネントの中身が少なかったので全体の記述量はほとんど同じですが、コンポーネントとしてまとめられる量が多かったり、何度も同じJSXを記述する場合ほどその効果は大きくなります。見た目もなんだかすっきりしていますよね。
複雑な処理になればなるほどコンポーネントの真価が発揮されるでしょう。

またコンポーネントには**クラスコンポーネント**と**関数コンポーネント**の２種類あります。それぞれ特徴をみていきましょう。

###クラスコンポーネント
クラスコンポーネントはclass定義で作成されるコンポーネントです。クラスコンポーネントを作成する場合には、`React.Component()`を継承することで作成できます。前述した例の`Greeting`もクラスコンポーネントです。
クラスコンポーネントではJSXをreturnするために**必ず**`render()`メソッドを定義する必要があります。メソッド以外にもクラスですのでconstructor(コンストラクタ)も定義することができます。

```react:src/App.js
import React, { Component } from 'react';

class Greeting extends Component {  // React.Componentを継承
  constructor() {
    .
    .  // ここでは省略します
    .
  }

  render() {  // JSXを返すrenderメソッド
    return(
      <h1>Hello, world.</h1>
    );
  }
}
```


###関数コンポーネント
関数コンポーネントは、コンポーネントを関数で定義することができます。定義の仕方は`function`でも書けますが、**アロー関数**で書くほうが記述量的にベターな気がします。

```react:src/App.js
import React from 'react';

const Greeting = () => {
  return(
    <h1>Hello, world.</h1>
  );
}
```
このようになります。
関数コンポーネントの中身は基本的に`render()`メソッドとなるので、クラスコンポーネントで記述していた`render()`は省略できます。

以前は、後述する状態(state)やライフサイクルを関数コンポーネントでは持つことができなかったので、その場合にはクラスコンポーネントを作成するといった区別がありました。
しかしReact 16.8で実装された**Hooks**を用いることで**関数コンポーネントでもクラスコンポーネントと同等の機能を持つことができる**ようになったので、今は基本的にコンポーネントは**Hooks**を用いて記述されることが多いようです。
Hooksに関する記事はまた別に出します。

#props
`props`とは、コンポーネントに引数として渡せるプロパティ（オブジェクト）です。

`props`がどんな役割を担うのか例で見てみましょう。

```react:src/App.js
const App = () => {
  return(
    <React.Fragment>
      <h1>I am taro, 10 years old.</h1>
      <h1>I am hanako, 8 years old.</h1>
      <h1>I am yuta, 11 years old.</h1>
    </React.Fragment>
  );
}
```
このようなJSXがあったとき、`<h1>`タグの中身は似たような内容ではありますが、全く同じではありません。でも共通する箇所が多いのでなんとかコンポーネントとしてまとめたいですよね。
そんなときに登場するのが`props`です。

では`props`を用いて上記のコードを書き換えてみます。

```react:src/App.js
const Greeting = props => {
  return(
    <h1>I am {props.name}, {props.age} years old.</h1>
  );
}

const App = () => {
  return(
    <React.Fragment>
      <Greeting name="taro" age="10" />
      <Greeting name="hanako" age="8" />
      <Greeting name="yuta" age="11" />
    </React.Fragment>
  );
}
```
書き換え前に比べすっきりしました。
ここで親コンポーネント`App`が子コンポーネント`Greeting`コンポーネントに渡している`name="..." age=...`が`props`です。

このようにコンポーネントを利用するうえで欠かすことのできない機能なのでしっかり抑えておきましょう。
propsを用いる場合には次のような注意点があります。

* propsの受け渡しは親コンポーネント→子コンポーネントのみ
* 子コンポーネント側からpropsの値を直接変更することはできない
* 子コンポーネントでは`props.データ名`でデータを参照する

#state
`state`とは、コンポーネント内部の状態を表す値です。
`props`とは違い、そのコンポーネント内でしか扱うことができず、かつ`setState()`を使うことでコンポーネント内で変更可能なのが特徴です。

クラスコンポーネントで`state`を使う場合は、基本的にコンポーネント作成時のコンストラクタ内で初期化します。`this.state`オブジェクトに値を指定することで、同コンポーネント内のメソッドで取得することができます。

```react:src/Counter.js
import React, { Component } from 'react';

class Counter extends Component {
  constructor(props) {
    super(props);
    this.state = {  // this.stateの初期化
      count: 0,
    };
  }

  render() {
    return(
      <div>count: {this.state.count}</div>
    );
  }
}
```
このような記述になります。`constructor(props)`や`super(props)`はおまじないみたいなものと覚えて大丈夫です。

`this.state`の初期値設定ができたので、値を`setState()`で変更してみましょう。

```react:src/Counter.js
import React, { Component } from 'react';

class Counter extends Component {
  constructor(props) {
    super(props);
    this.state = {  // this.stateの初期化
      count: 0,
    };
  }

  // this.state.countを+1するメソッド
  handleCountButton = () => {
    this.setState({count: this.state.count + 1});  // this.stateの更新
  }

  render() {
    //Countボタンをクリックしたらcountが+1されるJSX
    return(
      <React.Fragment>
        <div>count: {this.state.count}</div>
        <button onClick={this.handleCountButton}>Count</button>
      </React.Fragment>
    );
  }
}
```
ここでは`Count`というボタンを押すことで、`this.state.count`が+1されるというメソッド`handleCountButton()`を用いて更新をしてみました。目で追うと若干複雑に見えますが、１つずつ理解していけばそこまで難しくないと思います。

`state`も`props`と同様にコンポーネントを扱ううえで必要な機能なのでここでしっかり理解しておきましょう。最も重要な注意点は、`this.state`を**直接変更することができない**ことです。必ず`setState()`で変更しましょう。

###現在のReact
以前まではクラスコンポーネントでしか`state`を利用することができませんでしたが、React Hooksで追加された機能の`useState`を使うことで関数コンポーネントでも`state`を利用することができるようになりました。これにより最近のReactコンポーネントの主流は関数コンポーネントになっています。`useState`などReact Hooksについては前述したように別の記事にまとめたいと思います。


#2種類のrender()
今までのコードに`render()`が何回も登場していますが、この`render()`にも2種類あります。

* React.Componentのrender()
* ReactDOMのrender()

それぞれについて見てみましょう。

###React.Componentのrender()
[Component](#component)でも述べましたが、コンポーネント内で必ず定義する必要のあるメソッドが`render()`です。（ただし関数コンポーネントでは省略されることもあります。）

```react
class App extends Component {
  render() {
    return( /*返す要素*/ );
  }
}
```
コンポーネントに用いる`render()`は呼び出されると、`this.props`と`this.state`を調べReact要素などを返します。（詳細は[こちら](https://reactjs.org/docs/react-component.html#render)）

###ReactDOMのrender()
`ReactDOM.render()`のイメージとしては最終的にブラウザへレンダリングするためのメソッドです。

```react
ReactDOM.render(element, container[, callback])
```

よくReactの特徴として「**仮想DOM**」というワードを見かけると思いますが、それに起因するのが`ReactDOM.render()`です。
`ReactDOM.render()`メソッドが飛び出されると指定された`container`にReact要素をレンダリングします。このとき描画された結果のDOMを表したデータ構造が**仮想DOM**です。
再度`ReactDOM.render()`が呼び出されると、変更前後の仮想DOMの差分を計算し、最低限の操作をブラウザ上の実際のDOMに対して行います。

これら２種類の`render()`の役割をまとまると、

* 各Componentのrender()がそれぞれのパーツを作る
* ReactDOMのrender()がパーツを集めて１つにまとめてブラウザへ描画する

といったイメージかと思います。


#まとめ
Reactの基礎についてまとめてみました。とは言ってもまだ基礎の基礎くらいで、本当はまだまだこんなものではありません。とりあえず今回の記事のまとめです。

* Reactでは**JSX**が書ける
* **Component**はJSXを構成するUI部品
* **props**は親コンポーネントから子コンポーネントへ渡せる引数オブジェクト（子では変更不可）
* **state**はコンポーネント内部の状態を表す値（変更可）
* **render()**メソッドには２種類ある

今回は自身の知識の土台を固めるつもりでこのような記事を書きましたが、今後も必要に応じて色々とまとめてみたいと思います。


#参考資料
* [React公式サイト](https://ja.reactjs.org/)
* [React入門](http://www.tohoho-web.com/ex/react.html)
* [React入門 ～基礎編～](https://qiita.com/h-yoshikawa/items/4cde7fd891783c396a32#react%E3%81%AE%E5%9F%BA%E6%9C%AC)
* [BabelとES2015 – React入門](https://www.to-r.net/media/react-tutorial03/)
* [本とプログラミングと時々ミニブタ](https://pigblog.org/page/4)
* [Stateとは？ – React入門](https://www.to-r.net/media/react-tutorial07/)
* [ReactDOMのrender()とReact.Componentのrender()の違いを理解する](https://qiita.com/tatane616/items/9808f8861586fb2b2926)
* [Reactの基礎とReactDOMについて学ぶ_100DaysOfCodeチャレンジ13日目(Day_13:#100DaysOfCode)](https://qiita.com/yuta-ushijima/items/a8c3d01beb1fd9ac6de5)