React公式ドキュメントを読む23 Reactにおけるファイルの送信

前回からの続きです。 今回読むReact公式ドキュメントは「フォーム」ページの中盤です。

今回は、Reactにおけるファイルの送信について紹介します。ファイルの送信では state による制御ができないため、 ref というデータを利用します。refとはどのようなデータなのか、以下に詳しく見ていきましょう。

送信するファイルはユーザー側のみで設定できるもの、プログラム側では制御できない

HTMLにおいてファイルを送信するには、input要素のtype属性の値に”file”を指定します。例えば、以下のように指定すると、ユーザーは自分のデバイス内のファイルを選択してサーバーにアップロードできるようになります。

<input type="file" />

Reactにおけるファイルの送信についても、送信するファイルはユーザー側のみで設定できるものであり、プログラム側では制御できません。ファイルの送信のように、プログラム側では制御できない送信データを扱うコンポーネントを非制御コンポーネントと呼びます。

stateで制御する代わりに、refを使用する

Reactでフォームを作成する場合、可能な場合には制御コンポーネントとして作成して、stateでデータを制御するのが基本です。非制御コンポーネントは、あくもあでも制御コンポーネントを作成できない場合の代替手段となります。

ファイルの送信はプログラム側では送信ファイルを制御できないので、非制御コンポーネントとして作成することになります。制御コンポーネントではフォームのデータは React コンポーネントが扱いますが、非制御コンポーネントではフォームのデータは DOM に保持します。

Reactで送信ファイルを扱う実例

以下のコードは、Reactで送信ファイルを扱う実例です。

// FileInputコンポーネント
class FileInput extends React.Component {

  // コンストラクタ
  constructor(props) {
    // highlight-range{3}
    super(props);
    //メソッドをバインド
    this.handleSubmit = this.handleSubmit.bind(this);
    //Refを作成
    this.fileInput = React.createRef();
  }

  // クラスメソッド
  // 選択されたファイルをアラート表示する
  handleSubmit(event) {
    // highlight-range{4}
    event.preventDefault();
    alert(
      `選択されたファイル: ${
        this.fileInput.current.files[0].name
      }`
    );
  }

  // レンダリング要素を返す
  render() {
    // highlight-range{5}
    return (
      <form onSubmit={this.handleSubmit}>
        <label>
          アップロードするファイル:
          <input type="file" ref={this.fileInput} />
        </label>
        <br />
        <button type="submit">アップロード</button>
      </form>
    );
  }
}

// レンダリング
ReactDOM.render(
  <FileInput />,
  document.getElementById('root')
);

上記のサンプルソースをHTMLファイルにしたものが以下です。

https://programming-world.net/sample/react_doc/forms3-1.html

非制御コンポーネントでは、stateでデータを制御する代わりに、refを使用してDOMから値を取得します。

  • ref は React.createRef() を使用して作成されるデータです。上記コードでいえば、 this.fileInput = React.createRef(); のところでrefを作成しています。
  • ref は ref 属性を用いてReact要素に紐づけられます。上記コードでいえば、 <input type=”file” ref={this.fileInput} /> のところでReact要素に紐づけられています。
  • ref が render()メソッド内のReact要素に紐づけられると、ref の current 属性でそのノードにアクセスできるようになります。上記コードでいえば、this.fileInput.current.files[0].name のところでアクセスして利用しています。

上記の一連の動作は、「DOMノードへの ref を作成して、submitした際にrefを通じてファイルにアクセスしている」という説明にまとめられます。

次回へ続きます。