• トップ
  • ブログ一覧
  • React Hooks登場でコンポーネントはどう変わった?
  • React Hooks登場でコンポーネントはどう変わった?

    広告メディア事業部広告メディア事業部
    2021.01.11

    エンジニアになろう!

    React Hooks とは?

    React Hooks」とは、React16.8より追加された新機能です。

    これにより、クラスコンポーネントでしか使えなかった機能が、関数コンポーネントでも使えるようになりました。

    【React 公式ドキュメント - フックの導入】
    https://ja.reactjs.org/docs/hooks-intro.html

    今回は、ReactHooks 登場前後のコンポーネントを比較し、「記法がどのように変わったのか」を見ていきたいと思います!

    実装するサンプル

    違いを分かりやすくするために、以下のような機能を持ったコンポーネントを実装します。

    1. 状態としてcount という変数を持つ
    2. カウントアップボタンを押すことで、count をインクリメントする
    3. count は常に画面上に表示する
    4. コンポーネントのマウント時・状態の更新時・アンマウント時に、それぞれコンソール出力する

    それではさっそく、実装サンプルを見ていきましょう!

    クラスコンポーネントで実装した場合

    まずは、従来通り「クラスコンポーネント」で実装した場合です。

    従来の React の記法に慣れた方にとっては、少し冗長な表記になるかもしれません。

    1import React from "react";
    2
    3class NormalComponent extends React.Component {
    4  /*
    5   * コンストラクタ
    6   */
    7  constructor() {
    8    super();
    9
    10    /**
    11     * 画面の状態を初期化
    12     */
    13    this.state = {
    14      count: 0,
    15    };
    16  }
    17
    18  /**
    19   * コンポーネントマウント後処理
    20   */
    21  componentDidMount = () => {
    22    console.log("[NormalComponent] componentDidMount");
    23  };
    24
    25  /**
    26   * コンポーネント更新時処理
    27   */
    28  componentDidUpdate = () => {
    29    console.log("[NormalComponent] componentDidUpdate");
    30  };
    31
    32  /**
    33   * コンポーネントアンマウント前処理
    34   */
    35  componentWillUnmount = () => {
    36    console.log("[NormalComponent] componentWillUnmount");
    37  };
    38
    39  render = () => {
    40    const { count } = this.state;
    41    return (
    42      <>
    43        <p>{`This Component is NormalComponent (${count.toString()})`}</p>
    44        <button
    45          onClick={() => {
    46            // ボタンを押下したタイミングでthis.setStateを使いstateを加算する
    47            this.setState({ count: count + 1 });
    48          }}
    49        >
    50          Count Up
    51        </button>
    52      </>
    53    );
    54  };
    55}
    56
    57export default NormalComponent;

    ここがポイント!

    コンストラクタでコンポーネントの状態であるstate を初期化し、ボタン押下のタイミングでsetState を用いて更新します。

    また、コンポーネントがマウント・アンマウントされたタイミングや、状態が更新されたタイミングはそれぞれcomponentDidMount ,componentWillUnmount ,componentDidUpdate といった React のライフサイクルメソッドを用いて検知し、コンソールに出力しています。

    React Hooks を使った関数コンポーネントで実装した場合

    続いて、「React Hooks」を使った実装パターンを見てみましょう。

    React Hooks を使う際のルールとして、「関数コンポーネント中のトップレベル」で定義する必要があります。

    1import React, { useEffect, useState } from "react";
    2
    3const HooksComponent = () => {
    4  // マウントされたかどうかをisMountedで管理
    5  const [isMounted, setIsMounted] = useState(false);
    6  const [count, setCount] = useState(0);
    7
    8  // 第二引数に空の配列を設定することでマウント・アンマウント時のみ起動する
    9  useEffect(() => {
    10    // returnで関数を返却することで、
    11    // useEffectの状態監視が終了した(=アンマウントされた)タイミングで起動する
    12    return () => {
    13      console.log("[HooksComponent] useEffect willUnmount");
    14    };
    15  }, []);
    16
    17  // 第二引数にcountを含めた配列を設定することで、countの変更を監視する
    18  useEffect(() => {
    19    // isMountedの状態によりクラスコンポーネントでの
    20    // componentDidMountとcomponentDidUpdateを判別する
    21    if (isMounted) {
    22      console.log("[HooksComponent] useEffect disUpdate");
    23    } else {
    24      console.log("[HooksComponent] useEffect didMount");
    25      setIsMounted(true);
    26    }
    27  }, [count]);
    28
    29  return (
    30    <>
    31      <p>{`This Component is HooksComponent (${count.toString()})`}</p>
    32      <button
    33        onClick={() => {
    34          // ボタンを押下したタイミングでsetCountを使いcountを加算する
    35          setCount(count + 1);
    36        }}
    37      >
    38        Count Up
    39      </button>
    40    </>
    41  );
    42};
    43
    44export default HooksComponent;

    クラスコンポーネントでの実装に比べると、全体的に記述量が減っているのが一目瞭然ですね。

    ここがポイント!

    useState

    React Hooks では、useStatestate を定義しています。

    this.state やthis.setState なしでstate が扱えます。

    useEffect

    useEffect で、関数コンポーネントでライフサイクルメソッド機能が使用可能になります。

    クラスコンポーネントで使用した、以下の3つがまとまったものとイメージすれば分かりやすいでしょう。

    1. componentDidMount
    2. componentWillUnmount
    3. componentDidUpdate

    isMounted

    また、count に加えてisMounted という真偽値型の状態を持たせています。

    関数コンポーネントでは、コンポーネントがマウント済みかどうかの状態を独自で持つ必要があるためです。

    動作検証用コンポーネント

    実際に、お手元の環境で上記コンポーネントの動作検証をする場合、以下をお使いください。

    1import React from "react";
    2import NormalComponent from "./NormalComponent";
    3import HooksComponent from "./HooksComponent";
    4
    5export default class ComponentManager extends React.Component {
    6  constructor() {
    7    super();
    8
    9    this.state = {
    10      showComponent: true,
    11    };
    12  }
    13
    14  render = () => {
    15    const { showComponent } = this.state;
    16    return (
    17      <div>
    18        <button
    19          onClick={() => this.setState({ showComponent: !showComponent })}
    20        >
    21          {`Show/Hide Component`}
    22        </button>
    23        {showComponent ? (
    24          <div>
    25            <NormalComponent />
    26            <HooksComponent />
    27          </div>
    28        ) : null}
    29      </div>
    30    );
    31  };
    32}

    showComponent という状態を持ち、その値によってNormalComponent とHooksComponent の2種のコンポーネントのマウント・アンマウントを制御しています。

    「Show/Hide Component」のボタンをクリックすると、各コンポーネントのマウント・アンマウント処理が正常に行われていることを確認できます。

    さいごに

    今回は、「React Hooks 登場前後のコンポーネントの違い」について解説しました。

    クラスコンポーネントと React Hooks を用いた関数コンポーネントとでは、同じ挙動をさせる場合でも記法が大きく異なることが分かりますね。

    両者とも基本の記法を覚えておけば、2つを組み合わせて複雑な処理を実現することが可能です。

    ぜひ、しっかり覚えておきましょう!

    こちらの記事もオススメ!

    featureImg2020.07.17ライトコード的「やってみた!」シリーズ「やってみた!」を集めました!(株)ライトコードが今まで作ってきた「やってみた!」記事を集めてみました!※作成日が新し...

    広告メディア事業部

    広告メディア事業部

    おすすめ記事