Reactを学ぶVII 〜ライフサイクル知識編〜


## ■ はじめに

タイトルについて記事にしました。
この記事で得る内容は以下の通りです。

・ Reactの基礎知識が増える
・ Reactのライフサイクルについて

## ■ ライフサイクルとは

・ コンポーネントの「時間の流れ」
→ ユーザーの操作によって作られ、変更されたり、破棄されたりする循環
・ それぞれの段階で必要な処理を記述
→ Reactのライフサイクルメソッドというものを使う

## ■ 3種類のライフサイクルについて

#### ・ <font color="green">Mounting</font>
→ コンポーネントが配置される（生まれる）期間
（URLにアクセスしてページにReactで作ったコンポーネントが配置されるなど）

#### ・ <font color="blue">Updating</font>
→ コンポーネントが変更される（成長する）期間
（ユーザーがボタンを押した場合、ある箇所の色を変えるなど）

#### ・ <font color="red">Unmounting</font>

→ コンポーネントが破棄される（死ぬ）期間
（現在のページから別のページにアクセスするなど）

Reactではこの3つの期間で使えるメソッドが用意されている

## ■ なぜライフサイクルを使うのか

→ Reactコンポーネントの外に影響を与える関数を記述する時にライフサイクルを使う
（Reactで作ったVirtual DOMを変更する時やDB通信(API)、ログ出力、setstate( ) etc...）

・ 副作用
→ よくReactで、副作用のある処理を記述しようと言われますが、それは適切な場所（ライフサイクル）に配置すべき処理のことを指します

## ■ 主要メソッド(<font color="green">Mount</font>)

#### ・ constructor()
→ 初期化（stateなど）これからコンポーネントで使おうとしている変数など最初に定義する場合に使う

#### ・ render()
→ Virtual DOMを描画（JSXをリターン）

#### ・ compornentDidMount()
→ render()後に1度だけ呼ばれ、リスナーの設定やAPI通信に使われる

## ■ 主要メソッド(<font color="blue">Update</font>)

#### ・ render()
→ VDOMを再描画

#### ・ compornentDidMount()
→ 再render後に呼ばれるスクロールイベントや条件付きイベント

## ■ 主要メソッド(<font color="red">Unmount</font>)

#### ・ componentWillUnmount
→ コンポーネントが破棄される直前に使われる（リソースの開放やリスナーの解除など）

## ■ 例
例として、いいねボタンを作ってみます。前回書いたのをそのまま使います

① まず、`this.state`の中に`count: 0,`と書いて

```react:Blog.jsx
class Blog extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      isPublished: false,
      count: 0,
    };
  }
```

② `constructor`の中で宣言した`count`のstateを`Article`に渡すと、`Article`の中でcount数が分かる様になります

```react:Blog.jsx
  render() {
    return (
      <>
        <Article title={"Reactの使い方"} isPublished={this.state.isPublished} toggle={() => this.togglePublished()} count={this.state.count} />
      </>
    );
  }
```

③ 次に、`Article.jsx`に`<LikeButton />`というコンポーネントを記述して

```react:Article.jsx

// 中略

const Article = (props) => {
  return (
    <div>
      <h2>{props.title}</h2>
      <label htmlFor="check">公開状態：</label>
      <input type="checkbox" checked={props.isPublished} id="check" onClick={() => props.toggle()} />
      <LikeButton />
    </div>
  );
};
```

④ `LikeButton.jsx`というファイルを新規作成して、次の様に記述します

```react:LikeButton.jsx
import React from "react";

// 関数名はファイル名と合わせる
const LikeButton = (props) => {
  return <button>いいね数:{props.count}</button>; // propsを引数に受け、いいね数をprops.countという形で受け取る
};

export default LikeButton;
```

⑤ `Article.jsx`で`LikeButton`を`import`します

```react:Article.jsx
import LikeButton "./LikeButton";
```

次に`LikeButton`に`count`を渡すのですが、`Blog.jsx`からは`this.state.count`という内容を`count`という`props`で受け取っているので

```react:Blog.jsx
  render() {
    return (
      <>
        <Article title={"Reactの使い方"} isPublished={this.state.isPublished} toggle={() => this.togglePublished()} count={this.state.count} />
      </>
    );
  }
```

⑦ こちらも`props.count`という形で渡してあげると`LikeButton.jsx`も同じ様に参照できる様になります

```react:Article.jsx
const Article = (props) => {
  return (
    <div>
      <h2>{props.title}</h2>
      <label htmlFor="check">公開状態：</label>
      <input type="checkbox" checked={props.isPublished} id="check" onClick={() => props.toggle()} />
      <LikeButton count={props.count} />
    </div>
  );
};
```

ただ、現状はボタンを押しても何も変わりませんので、ボタンをクリックしたらいいね数を増やす処理を書きます

![今の感じ.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/772631/fcec55ff-8a70-9fc5-4dd5-9d9911d0b256.gif)

⑧ `countUp`変数を作り、呼び出されたら`state`を変更します（countの現在の値に+1する）

```react:Blog.jsx
countUp = () => {
  this.setstate({
    count: this.state.count + 1,
  });
};
```

⑨ 今回はライフサイクルを使うので、イベントリスナーを設定します

```react:Blog.jsx
componentDidMount() {
  document.getElementById("counter").addEventListener("click", this.countUp);
}
// this.countUp()の様な書き方だと無限ループしてしまうので、関数型（） =>及び、関数だけを渡す

```

⑩ イベントリスナーの設定先に`id`を設定します

```react:Article.jsx
// 関数名はファイル名と合わせる
const LikeButton = (props) => {
  return <button id={"counter"}>いいね数:{props.count}</button>; // propsを引数に受け、いいね数をprops.countという形で受け取る
};
```

これでボタンをクリックすると、いいねが増える様になりました

![カウントアップされていく.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/772631/6f13530c-88b9-9cf3-7428-534cad690644.gif)