Reactを使用したWebアプリケーションを開発する場合、ファイルアップロードは一般的な機能の一つです。しかし、Reactにはファイルアップロードのための組み込みの機能がありません。この記事では、Reactでファイルアップロードを実現する方法を紹介します。
1. ファイルアップロードの基本
ファイルアップロードは、HTMLのformタグを使用して実現されます。formタグには、ファイルを選択するためのinputタグがあります。このinputタグには、type属性をfileに設定する必要があります。
<form>
  <input type="file" />
  <button type="submit">アップロード</button>
</form>
このフォームを送信すると、選択されたファイルがサーバーに送信されます。サーバー側で、ファイルを受け取って保存する処理を実装する必要があります。
2. Reactでのファイルアップロード
Reactでファイルアップロードを実現する場合、通常のフォームの送信とは異なる方法を取る必要があります。Reactは、フォームの送信を制御するためのstateを提供しています。これを利用して、ファイルを選択し、送信することができます。
まず、inputタグにonChangeイベントを設定して、選択されたファイルをstateに保存します。
import { useState } from "react";
function FileUpload() {
  const [selectedFile, setSelectedFile] = useState(null);
  function handleFileChange(event) {
    setSelectedFile(event.target.files[0]);
  }
  return (
    <form>
      <input type="file" onChange={handleFileChange} />
      <button type="submit">アップロード</button>
    </form>
  );
}
次に、フォームの送信を制御するための関数を定義します。この関数では、選択されたファイルをサーバーに送信するためのリクエストを実行します。
import { useState } from "react";
function FileUpload() {
  const [selectedFile, setSelectedFile] = useState(null);
  function handleFileChange(event) {
    setSelectedFile(event.target.files[0]);
  }
  function handleFormSubmit(event) {
    event.preventDefault();
    const formData = new FormData();
    formData.append("file", selectedFile);
    fetch("/api/upload", {
      method: "POST",
      body: formData
    })
      .then(response => {
        //
        // レスポンスの処理
      })
      .catch(error => {
        // エラーの処理
      });
  }
  return (
    <form onSubmit={handleFormSubmit}>
      <input type="file" onChange={handleFileChange} />
      <button type="submit">アップロード</button>
    </form>
  );
}
このように、フォームの送信を制御するための関数で、選択されたファイルをFormDataオブジェクトに追加し、fetch関数でサーバーに送信します。
3. ファイルアップロードの進捗を表示する
大きなファイルをアップロードする場合、ファイルの送信に時間がかかることがあります。ユーザーに進捗状況を表示することで、ユーザー体験を向上させることができます。
ファイルの送信中には、fetch関数がPromiseを返します。このPromiseを利用して、ファイルの送信進捗を監視することができます。
import { useState } from "react";
function FileUpload() {
  const [selectedFile, setSelectedFile] = useState(null);
  const [uploadProgress, setUploadProgress] = useState(0);
  function handleFileChange(event) {
    setSelectedFile(event.target.files[0]);
  }
  function handleFormSubmit(event) {
    event.preventDefault();
    const formData = new FormData();
    formData.append("file", selectedFile);
    fetch("/api/upload", {
      method: "POST",
      body: formData,
      onUploadProgress: progressEvent => {
        const progress = Math.round(
          (progressEvent.loaded / progressEvent.total) * 100
        );
        setUploadProgress(progress);
      }
    })
      .then(response => {
        // レスポンスの処理
      })
      .catch(error => {
        // エラーの処理
      });
  }
  return (
    <form onSubmit={handleFormSubmit}>
      <input type="file" onChange={handleFileChange} />
      <button type="submit">アップロード</button>
      {uploadProgress > 0 && <div>アップロード中...{uploadProgress}%</div>}
    </form>
  );
}
このように、fetch関数のオプションであるonUploadProgress関数を定義し、ファイルの送信進捗をstateに保存します。そして、stateが0より大きい場合に、進捗状況を表示するようにします。
まとめ
Reactでファイルアップロードを実現する方法について紹介しました。ファイルの選択や送信は、通常のHTMLのフォームと同様に行います。Reactでのファイルアップロードは、フォームの送信を制御するためのstateを利用して実現します。また、ファイルの送信進捗を表示する