React超入門

## はじめに
本記事は初めてreactを触る人向けに書いています。
reactってなんだ？どう書いたらいいの？という初歩的な内容をまとめています。

※ライフサイクルの説明は長くなるので割愛させていただきました。
以下の記事が秀逸なのでこちらを紹介させていただきます。
https://qiita.com/Julia0709/items/3c3fc8d29fd2e56ed7a9

## Reactとは
FaceBookによって開発されたフロントエンドフレームワークで、Reactはリアクティブ・プログラミングで、値がどのように伝わっていくかを重視しています。

従来のjsとの違いとして、表示を更新するとき予め用意した値を設定しておけば元の値を変更すると表示も自動的に更新されます。

また、Reactは直接DOM操作するのではなく、プログラム的に仮のDOMを構築してそれを操作します。
これを**仮想DOM**といいます。この仮想DOMは通常のDOMに比べて軽くて高速です。
## React開発に必要なもの
- Node.js:　JavaScriptの実行環境（必須）
- Create React App:　Node.jsに組み込まれた**npx**を使ってターミナルで **`npx create-react-appフォルダ名`** を入力して実行（スターターキットのようなもの。自分で環境構築ができる場合は不要）
- React Developer Tools:　デバッグ用ツール。Reactを使った開発をするならあった方が良い。（ブラウザの拡張ツール）

※トランスパイラ等はCreate React Appで用意されているのでここでは省略します。

## JSX
Reactでは、HTMLのタグを直接JavaScriptのスクリプトに記述する仕組みを持っています。これを**JSX**といいます。JSXを使用することでようやくReactを使うメリットを実感できると思います。

JSXを使った記述と使わない記述の違いを見ていきます。
ブラウザに表示されている**ここに表示されます。**を**Hello World**に表示を変更させます。

```html
<div id="root">ここに表示させます。</div>
```
JSXなし

```js
import React from 'react';　//インストールしたreactを使うためにインポートしています。（今回はcreate-react-appで必要な物をまとめてインストールしているので、新しくインストールする必要はありません。）
const rootId = document.querySelector('#root');
const element = React.createElement (
    'p', {}, 'Hello World'
);
ReactDOM.render(element, rootId);
```
JSX

```js
import React from 'react';
ReactDOM.render(<p>Hello World</p>,document.getElementById('root'));
```
JSXを使用した方が記述量が減り、可読性が上がるのが分かりますね。
JSXを使わない場合以下の**React.createElement**という箇所で仮想DOMのエレメントを作成しています。

```js
const element = React.createElement (
    'p', {}, 'Hello World'
);
```
**React.createElement**の第一引数にはタグ名、第二引数にはそのエレメントに用意される属性オブジェクト（必要ない場合はからのオブジェクトを指定）、第三引数には作成するエレメントの内部に組み込まれるものを用意します。

まとめると以下のようになります。

```js
React.createElement(タグ名、属性、中に組み込む物);
```

作成した仮想DOMエレメントを**ReactDOM**オブジェクトの**render**メソッドを使いレンダリングします。

JSXを使う場合はシンプルに
`pタグ`で表示したい**Hello World**を囲い、**render**メソッドを使いレンダリングしています。

そして、ブラウザにアクセスすると差分を検知し、`divタグ`で囲われた**ここに表示されます。**が**Hello World**に書き換わっていると思います。

デバッグツールで確認すると以下のように変更されていることが確認できます。これはJSXで記述した方でも同じように表示されるはずです。

```html
<div id="root"><p>Hello World</p></div>
 ```

どちらの書き方が良いかは一目瞭然ですね。

JSXを使わないと表示するタグを**createElement**で1つずつ作成していかなければなりません。その煩雑さを解消するためにJSXを使うという訳です。

しかし、JSXは[**babel**](https://babeljs.io/docs/en/index.html
)によってトランスパイルされることで初めて成り立っています。どのようにbabelが変換しているかを頭でイメージできるかできないかでは習熟度が全然違ってきます。

## コンポーネント
Reactではコンポーネント毎に管理する分割統治の概念があります。
ここでは基本的なコンポーネントの書き方を書いていきます。

```js
//index.jsx
import React from 'react';
import ReactDOM from 'react-dom';
import App from '.Components/app'; //Appコンポーネントがある階層を指定してインポートする。
ReactDOM.render(<App />,document.getElementById('root'));
```
```js
//app.js
class App extends React.Component {
    render() {
        return <p>Hello World</p>
    }
}
export default App;//Appコンポーネントを他ファイルでインポートできるようにエクスポートする。
```
上記では**React.Component**を継承した**Appクラス**を作って、**render()**メソッドでJSXをreturnしています。これにより**ReactDOM.render()**から呼び出した際にJSXで出力されます。

このようにコンポーネント化することにより以下のメリットがあります。

- 再利用性が高い
- 保守性が高い
- 管理がしやすい
- アトミックデザインと相性が良い（パーツ・コンポーネント単位で定義していくUIのデザイン手法）

コンポーネントはスクリプト内に複数のコンポーネントを書いて、組み合わせて表示を作成することができます。

また、上記の例では敢えてファイルを複数に分ける想定で書いていますが、これはコンポーネントが複数存在する想定での書き方で、今回のようにテキストを表示させるだけの場合は1ファイルで完結させた方がシンプルで良いでしょう。
## 状態管理
Reactでは保管した状態を操作するために以下のようなモノが用意されています。

- props
　親コンポーネントから渡されたプロパティです。propsはimmutableなデータで、変更ができません。
- state
　コンポーネントが持っている状態です。stateはmutableなデータで変更することができます。

**state**の初期値を受け取るには**this.state**で値を取り出します。

簡単に説明すると、親コンポーネントで保持しているstateの値を子コンポーネント側でpropsで受け取ります。stateを**更新**することでコンポーネントの表示を変えたりしています。

以下のようにapp.jsを書き換えます。

```js
//app.js
import React, { Component } from 'react';
class App extends Component {
    constructor(props){
        super(props);
        this.state = {
            clickCount: 0
        };
        this.handleClick = this.handleClick.bind(this);
    }
    handleClick() {
        this.setState((state) => ({
            clickCount: state.clickCount + 1
        }));
    }
    render(){
        return(
            <div>
                <button onClick={this.handleClick}>ButtonCount</button>
                <h1>{this.state.clickCount}</h1>
            </div>
        );
    }
}
export default App;
```

クリックしたら値が更新され数字が1つずつ増えていきます。
最初に画面に表示されている0の数字は**constructor**で設定しており、ステートの値はオブジェクトリテラルとして記述します。

これで**this.state**の中から設定した値を取り出して利用することができるようになりました。
初期状態として表示される**0**は**constructor**で設定した**0**が表示されているということです。

そしてButtonCountボタンを押下すると、`<h1>`タグで挟んでいる**`{this.state.clickCount}`**の値が**更新**されます。

今回はapp.jsで完結させていますが、**clickCount**の値を子コンポーネントに渡して、
子コンポーネントで値を表示するという実装だったとすると以下のようになります。

```js
//app.js
import React, { Component } from 'react';
import Child from '.Component/child.js';
class App extends Component {
    constructor(props){
        super(props);
        this.state = {
            clickCount: 0
        };
        this.handleClick = this.handleClick.bind(this);
    }
    handleClick() {
        this.setState((state) => ({
            clickCount: state.clickCount + 1
        }));
    }
    render(){
        return(
            <div>
                <button onClick={this.handleClick}>ButtonCount</button>
                <Child clickCount={this.state.clickCount} />
            </div>
        );
    }
}
export default App;
```
```js
//child.js
import React, {Component} from 'react';
class Child extends Component {
    render() {
        console.log(this.props);
        return <h1>{this.props.clickCount}</h1>
    }
}
export default Child;
```
親コンポーネントの**`<Child clickCount={this.state.clickCount} />`**箇所で子コンポーネントに値を渡し、子コンポーネントの**`{this.props.clickCount}`**箇所で親コンポーネントから渡された値を受け取り表示しています。

**`console.log`**で実際受け取っている値が見ることができます。

## おわりに
今回のように小規模開発であれば問題ないのですが、大規模開発になるとコンポーネントも増えて、propsのバケツリレーになってしまいます。
このバケツリレーを避けるために**Redux**というReactが扱う状態を管理するフレームワークなどを使うと良いでしょう。
[Redux公式]
(https://redux.js.org/introduction/getting-started)
[Redux超入門]
(https://qiita.com/YU01BLC/private/b294344c71b85aecfe5a)　←さらっと理解したい人向けに書いたので良かったら覗いてみてください。