React の「部品」のライフサイクルとリファレンス

記事
IT・テクノロジー

React の「部品」のライフサイクルとリファレンス

React でも、表示に利用する「部品」にはライフサイクルがあります。Vue の公式チュートリアル(英語版)では、この「部品」のライフサイクルをリファレンスの機能を使って体験するステップがありました。React でも似たようなやり方で同じような機能が実現できます。


React の表示の更新の例外

これまで紹介してきたように、React で表示データが更新に合わせて表示も更新する場合には、「ステート」を利用して管理するのが基本です。 今回取り上げるれでは、例外的にステートを利用しないでも表示の更新ができる例です。

import React, { useEffect } from "react";
import "./styles/step9.css";
export default function Step9() {
  return (
    <React.Fragment>
      <div className="step9">
        <p>hello</p>
      </div>
    </React.Fragment>
  );
}
Vue のチュートリアルと同様に、最初は、単純に「hello」を表示するように、直接、HTML に相当する部分(JSX)に「hello」を書いて表示させています。当然、表示は、「hello」が表示されます。

この記述を変更して、HTML に相当する部分で指定した、「hello」を「mounted!」に上書きします。 やり方は、Vue の公式チュートリアルで利用しているリファレンスを使っています。

React でも Vue でも似たような仕組みがあって、HTML の部品(DOM:Document Object Model)をプログラムで操作するために、似たような物(=仮想 DOM)という考え方を使ってプログラムに取り込んでいます。この部品を指す(リファレンス)を使って、表示するデータを操作しているのがこの課題で使っている実装方法になります。簡単に言うと、部品を「箱に見立てて」その部品が持っている情報を上書きしています。

以下のコードが、表示の準備ができた時に、表示のデータを更新する実装例です。

import React, { useEffect } from "react";
import "./styles/step9.css";
export default function Step9() {
  const ref: React.RefObject<HTMLParagraphElement> =
    React.createRef<HTMLParagraphElement>();
  useEffect((): void => {
    if (ref.current) {
      ref.current.textContent = "mounted!";
    }
  });
  return (
    <React.Fragment>
      <div className="step9">
        <p ref={ref}>hello</p>
      </div>
    </React.Fragment>
  );
}
React では、「_useEffect()_」と言う関数を利用すると、部品が Web ブラウザで表示できる状態になった時に、この関数が呼び出されて値が更新されます。

通常の React の処理では、変数が更新された事を検出して、この仮想 DOM の内容を更新しているのですが、この例では、仮想 DOM を直接更新するため、ステートで管理しなくても、表示が更新される仕組みになっています。

この変更を加えることで、表示が「hello」から「mounted!」に変わります。

ライフサイクルを利用した初期化

表示の初期化を行うのに、一番シンプルな方法は、部品を作成する際に初期化してしまうのが簡単でわかりやすい方法になります。 例えば、「_useState()_」を利用すれば、ステート管理が必要な変数に初期値を設定する事が可能です。

しかし、データをネットワークから取得する場合など、処理が非同期になる場合には、とりあえず部品作成時には、仮の値で初期化をしておきます。その上で、別の処理でデータをネットワークで取得した上でデータを設定するという方法が必要になる場合もたくさんあります。そうした時に、今回紹介したような「_useEffect()_」を使ってデータの設定を行います。

React でも幾つか別の初期化方法がある!

今回は、React Hook を使う場合を例に紹介しています。 しかし、React では、既に紹介したように、Class ベースの部品の作成も可能です。その場合には、「_useEffect()_」の代わりに、予め用意されたメソッド(method)を利用すると同じような機能を実現できます。この場合には、「_componentDidMount()_」を使うと上で紹介したような機能が実現できます。

import React, { useEffect } from "react";
import "./styles/step9.css";
export default class Step9 extends React.Component {
  private ref: React.RefObject<HTMLParagraphElement> =
    React.createRef<HTMLParagraphElement>();
  componentDidMount():void {
    if (this.ref.current) {
      this.ref.current.textContent = "mounted!";
    }
  }
  render(): JSX.Element {
    return (
      <React.Fragment>
        <div className="step9">
          <p ref={this.ref}>hello</p>
        </div>
      </React.Fragment>
    );
  }
}
Typescript 特有の書き方をしていますが、記述的には、Vue の場合に書き方に似ています。

どちらの書き方を使うかは、プログラムする人の好みという要素が強いかと思います。この連載では、基本的に React Hookd を使った書き方を中心にお届けしていますので、この書き方は参考として挙げています。

ステート管理とリファレンスの違いは?

既に簡単に説明していますが、ステート管理による表示の更新と、今回のリファレンスを使った表示では表示の更新の仕組みに違いがあります。

通常の React の表示の場合には、「React のフレームワーク」が仮想 DOM と呼ばれる HTML の「部品」に相当する部分のデータの更新を行なっています。従って、通常は、変数を使って、変数が更新された事を見つけて、仮想 DOM の更新を行います。つまり、通常の処理の場合、ステートを使って変数の更新を見つけないと表示の更新ができないという事になります。

ところが、今回の例の場合には、リファレンスを使って、「あなたが書いているプログラム」がこの仮想 DOM の更新を行なっていることになります。したがって、「部品」を直接更新しているので、ステートで更新を管理する必要がありません。

この二つの処理は、結果的には、似たような動作に見えますが、実際のプログラムの動作は違ってきます。

今回と同じような機能を、変数を使って「React のフレームワーク」を使って、値を更新することも可能です。

<p>{ value }</p>
のように、「_value_」という関数を使って表示の値を指定することができます。 この変数をステートを使って管理すれば、全く同じ機能を実現できます。

const [value, setValue]: [
  string,
  React.Dispatch<React.SetStateAction<string>>
] = useState("hello");

useEffect((): void => {
  setValue("mounted");
});
のように書けば機能的には同じになります。

ここで注意が必要なのは、この二つの方法をごちゃ混ぜにして使わないという事です。

<p ref={ref}>{value}</p>
のように書いて、「_ref_」を直接操作して、値を更新してしまった場合、この仮想 DOM の表示データは、「_value_」とは別のものになります。つまり、直接操作した後は、React のフレームワークを使った仕組みで、「_value_」の値を更新しても、表示を更新することができなくなります。この場合、表示を更新するには、リファレンスを使って、仮想 DOM のデータを直接操作する以外に更新することはできなくなります。

まとめ
今回は、React の表示の部品のライフサイクルを体験する課題でした。 表示の部品の初期化は、部品のライフサイクルに応じてデータを上書きする事ができます。今回紹介している、リファレンスを使う方法は、あなたの書くプログラムが直接、HTML の部品に相当する、仮想 DOM のデータを操作するやり方になります。

これは通常の、React のフレームワークが変数の更新を見つけて表示を更新する仕組みとは違ったやり方になります。プログラムを書く際には、この仕組みの違いをよく理解して、この二つの違う方法をきちんと使い分ける必要があります。
サービス数40万件のスキルマーケット、あなたにぴったりのサービスを探す