React で入力フィールドの文字を表示する

記事
IT・テクノロジー

React で入力フィールドの文字を表示する

ステップ5では入力フィールドに入力された文字を Reactde 表示する方法です。これも、React と Vue では若干違ったやり方になります。この記事では React で実現する二つの方法を紹介しています。

リファレンスを使う方法

Vue では「v-model」という方法を使って、入力フィールに入力された文字と変数を結びつけていました。(binding)React でも似たような機能としてリファレンス(reference)ができます。

import React, { useState } from "react";
import "./styles/step5.css";

export default function Step5(): JSX.Element {
  const fieldValue: React.RefObject<HTMLInputElement> =
    React.createRef<HTMLInputElement>();
  const [value, setValue] = useState("");
  return (
    <React.Fragment>
      <div className="step5">
        <input type="text" ref={fieldValue} onChange={() => getValue()} />
        <p>{value}</p>
      </div>
    </React.Fragment>
  );
  function getValue(): void {
    if (fieldValue.current) {
      setValue(fieldValue.current.value);
    } else {
      setValue("");
    }
  }
}
React の場合は、入力フィールドに入力された文字(データ)というよりは、入力フィールド自体を変数と結びつけるというイメージです。 したがって、入力された文字(データ)はこの例では、「_fieldValue.current.value_」になります。

そこで、この値を HTML に相当する部分(JSX)に書けば、入力フィールドに入力された文字を表示できそうですが、React の場合は、値が変化した場合に表示を更新したい場合には、「ステート(state)」の機能を使う必要があります。

したがって、入力内容が更新されたイベント処理で、ステート管理された変数に入れる必要があります。

このやり方が比較的 Vue のバインディングの機能に近い形での実装になります。

別の方法の方が一般的

同じ機能を React で実現する方法ですが、一般的には別の方法で書く場合が多くなっています。

import React, { useState } from "react";
import "./styles/step5.css";

export default function Step5(): JSX.Element {
  const fieldValue: React.RefObject<HTMLInputElement> =
    React.createRef<HTMLInputElement>();
  const [value, setValue] = useState("");
  return (
    <React.Fragment>
      <div className="step5">
        <input
          type="text"
          ref={fieldValue}
          onChange={(e: React.ChangeEvent<HTMLInputElement>) => getValue(e)}
        />
        <p>{value}</p>
      </div>
    </React.Fragment>
  );
  function getValue(e: React.ChangeEvent<HTMLInputElement>):void {
    const currentValue: string = e.currentTarget.value;
    setValue(currentValue);
  }
}
のように書く事ができます。 実は、入力フィールドの文字(データ)は、入力データの更新イベントのデータに含まれているので、それをステート管理している変数に入れてあげれば、リファレンスの変数を作る必要はありません。

今回のポイントは?

今回に限った事ではありませんが、React を利用する場合、変数の値が更新された場合に表示も更新したい場合には、変数を「ステート(state)」で管理する必要があります。 もう一つは、React と Vue では変数の値の更新の検出のやり方が違います。 例えば、今回の例では、変数「fieldValue」は、入力フィールドを示しています。入力フィールドの文字(データ)は、「fieldValue.current.value」になります。したがって、この変数自体は JSON オブジェクトということになります。React の場合、この変数は JSON オブジェクトを入れる「箱」として扱われているので、同じ「箱」を使っている場合、箱の中身が変わっても更新されたとは見なされない仕組みになっています。(immutable)

ところが、Vue の場合には、JSON オブジェクトの中身の更新もイベントとして検出が可能になっています。(mutable) したがって、React を利用する場合には、JSON オブジェクトや配列を扱う場合には注意が必要です。

React と Vue は似ていますが、この部分が大きく違っています。実は、この辺りも、初心者には Vue をお勧めする理由です。 Vue の方が、変数の更新時の扱いがシンプルで扱いやすいからです。

Typescript の面倒な所

もう一つ、今回のサンプルコードを見て気づくことがあります。 それは、「型」をきちんと宣言に入れる事です。Typescript の利点を最大限に利用するには、型をきちんと変数や定数、関数のインターフェースに結びつけてコンパイル時に型のチェックを出来るだけ行う必要があります。 ところが、この例を見るとお分かりかと思いますが、見慣れない型がたくさん出てきています。


....
const fieldValue: React.RefObject<HTMLInputElement> =
    React.createRef<HTMLInputElement>();
....
  function getValue(e: React.ChangeEvent<HTMLInputElement>):void {
    const currentValue: string = e.currentTarget.value;
    setValue(currentValue);
  }
などが良い例です。型も一般的な型である文字型(string)や数値型(number)などは、比較的わかりやすいので慣れれば余り問題なく宣言に書く事ができます。 ところが、上の例では、「React 特有の型」だったり、今回はありませんが、外部のモジュールを取り込んだ際には、「モジュール特有の型」というのが出てきます。 モジュール特有の型というのは、例えば、Firebase などを使う場合には、Firebase の実装で作られた Javascript(Typescript)では標準で定義されていない型があります。

こうした、「特有の型」は、初心者には特にわかりにくいもので、Typescript の利用に際して大きなハードルになっている場合がたくさんあります。

ではどうすれば良いかというと、方法は二つです。

* 曖昧な型を使う
* 高機能のエディタや IDE を使う
曖昧な型というのは、「any」という型を使ってしまう方法です。 例えば上の例では

....
const fieldValue: any = React.createRef<HTMLInputElement>();
....
  function getValue(e: any):void {
    const currentValue: string = e.currentTarget.value;
    setValue(currentValue);
  }
のように、型が分からないものを「any」で置き換えてしまう方法です。 ただし、「any = 何でも良い」という意味なので、型のチェックは厳密には行われなくなります。(チェックが甘くなります) このように記述した場合には、基本的に Javascript で書いた場合と大きな違いはなくなってしまうことになります。

そう考えると、出来るだけ型を入れた方が良いことになります。 最近の高機能のエディタや、IDE などでは、インポートするモジュールの情報などから、型の選択の支援をしてくれる機能がついている場合が多くなっています。 こうした機能を活用すると、実際にモジュールのドキュメントやソースコードを読まなくても、比較的簡単に型がわかります。

できればこうした機能を活用して、きちんと型を意識したコードを書いた方が品質がよくバグの少ないコードになります。

まとめ
この記事では、Vue の公式チュートリアル(英語版)のステップ5の「バインディング」の機能に近い React の記述方法を紹介しています。 Vue と React は似ていると言われていますが、今回の例でも、細かい所は書き方の「コンセプト」が微妙に違っています。

特に初心者の場合、「どうして」と疑問に思う点も多いかと思いますが、初心者の場合はまずは「書き方を覚える」事を優先してください。 まずは、正常に動作するコードを書けるようになった上で「何故」を解決するという二段階で学習する方が進捗が早くなります。

一方で、Typescript の活用は多少時間が掛かっても、出来るだけ「型を意識した」プログラムに慣れるために Typescript でプログラムを書く習慣をつけた方が結果的にバグが少なく、読みやすく管理しやすいプログラムになります。最近の、高機能のエディタや IDE を活用すると、コツさえ掴めば、型を正確に入れたプログラミングが簡単にできます。
サービス数40万件のスキルマーケット、あなたにぴったりのサービスを探す