React Context APIでフォーム管理を効率化!初心者向け実践ガイド
生徒
「Reactで大きな入力フォームを作っているのですが、名前やメールアドレスの情報をあちこちの部品に渡すのが大変です。もっと楽に管理する方法はありませんか?」
先生
「そんな時こそコンテキストエーピーアイ(Context API)の出番です。これを使えば、入力された情報をアプリ全体の共有物として、どこからでも簡単に取り出せるようになりますよ。」
生徒
「共有物ですか!でも、複数の入力欄があると、プログラムが複雑になりそうで不安です。」
先生
「大丈夫です。一つずつ手順を踏めば、驚くほどスッキリしたコードになります。実際の書き方を一緒に見ていきましょう!」
1. Reactのフォーム管理とContext APIの役割
ウェブサイトで名前や住所を入力する「フォーム」は、プログラムにとって非常に重要な部分です。通常、リアクト(React)でフォームを扱うときは、入力された文字を「ステート(State)」という一時的な記憶場所に保存します。
しかし、入力欄が増えたり、入力した内容を別の画面で表示したかったりする場合、情報を「バケツリレー」のように順番に手渡ししていく必要があります。これは非常に手間がかかり、間違いのもとになります。そこで、コンテキストエーピーアイ(Context API)を使います。これは、アプリ全体で使える「大きな共有の箱」を作る仕組みです。この箱の中にフォームの情報を入れておけば、どの部品からでも直接中身を覗いたり、書き換えたりすることができるようになります。パソコンを触ったことがない方でも、家族全員で書き込める「共有のメモ帳」をリビングに置くようなイメージだと考えてください。
2. フォーム用のコンテキストを作成しよう
まずは、フォームの情報を入れるための「専用の箱」を作成することから始めます。これを「コンテキストの作成」と呼びます。作成には createContext という命令を使います。
この箱を準備することで、名前やメールアドレスといった複数の情報をひとまとめにして管理する準備が整います。まずは基本となる「箱の定義」をコードで見てみましょう。ここでは、初期値として空の情報を設定しておきます。
import React, { createContext, useState } from "react";
// 1. フォームの情報を入れるためのコンテキスト(共有の箱)を作成します
export const FormContext = createContext();
// 2. 情報を提供するための「プロバイダー」という部品を作ります
export function FormProvider({ children }) {
// 名前とメールアドレスを保存する場所を作ります
const [formData, setFormData] = useState({
userName: "",
email: ""
});
return (
<FormContext.Provider value={{ formData, setFormData }}>
{children}
</FormContext.Provider>
);
}
3. 入力フォームの部品を作って情報を書き込む
次に、実際に文字を入力する欄を作ります。ここで大切なのは、入力した瞬間に「共有の箱(コンテキスト)」の中身を書き換えるという動きです。これには useContext(ユーズコンテキスト)という機能を使います。
入力欄に文字が打ち込まれるたびに、オンチェンジ(onChange)という命令が走り、共有の箱の中身が最新の状態に更新されます。これにより、常にアプリ全体が最新の入力内容を把握できるようになります。プログラミング未経験の方でも、キーボードを叩くたびに共有メモ帳が自動で書き換わっていく様子を想像してみてください。
import React, { useContext } from "react";
import { FormContext } from "./App";
function InputFields() {
// 共有の箱から、データと書き換え用の関数を取り出します
const { formData, setFormData } = useContext(FormContext);
const handleChange = (e) => {
const { name, value } = e.target;
// 古い情報を残したまま、新しい文字だけを上書きします
setFormData({ ...formData, [name]: value });
};
return (
<div className="p-3 border rounded shadow-sm">
<div className="mb-3">
<label className="form-label">お名前</label>
<input
name="userName"
className="form-control"
onChange={handleChange}
/>
</div>
<div className="mb-3">
<label className="form-label">メールアドレス</label>
<input
name="email"
className="form-control"
onChange={handleChange}
/>
</div>
</div>
);
}
4. 入力された内容を別の場所で表示する
コンテキストの素晴らしいところは、入力している場所とは全く別の部品で、その内容をリアルタイムに表示できる点です。例えば、入力フォームのすぐ横に「確認画面」を置くようなケースです。
確認画面の部品では、入力用の関数は必要ありません。ただ、共有の箱から「今のデータ」を取り出して画面に出すだけです。このように、役割ごとに部品を分けられるのがリアクトの大きな特徴です。これによって、画面が複雑になっても整理整頓された状態を保つことができます。
import React, { useContext } from "react";
import { FormContext } from "./App";
function PreviewArea() {
// 共有の箱から、表示したいデータだけを取り出します
const { formData } = useContext(FormContext);
return (
<div className="mt-4 p-3 bg-light border">
<h3>入力内容の確認</h3>
<p><strong>お名前:</strong> {formData.userName}</p>
<p><strong>メール:</strong> {formData.email}</p>
</div>
);
}
5. フォームのリセット機能を実装する
たくさんの項目を入力した後、一気にすべてを消去して空にしたい時がありますよね。コンテキストを使えば、リセットボタンも簡単に作れます。共有の箱を管理している大元の関数を呼び出して、中身を空っぽにする命令を出すだけです。
このとき、入力欄の「値(value)」もコンテキストのデータと連動させておくことがポイントです。そうすることで、プログラム側でデータを消した瞬間に、画面上の入力欄からも文字がパッと消えるようになります。これを「制御されたコンポーネント」と呼びます。初心者の方は、画面とプログラムが鏡合わせのように動く仕組みだと理解してください。
import React, { useContext } from "react";
import { FormContext } from "./App";
function ResetButton() {
const { setFormData } = useContext(FormContext);
const handleReset = () => {
// データを初期状態(空っぽ)に戻します
setFormData({ userName: "", email: "" });
};
return (
<button className="btn btn-danger w-100" onClick={handleReset}>
すべての入力をクリア
</button>
);
}
6. エラーチェック(バリデーション)の追加
フォーム管理の実践として欠かせないのが、入力ミスがないかチェックする「バリデーション」です。メールアドレスに「@」が入っているか、名前が空欄ではないか、といった確認作業です。
このエラー情報も、コンテキストの共有の箱に入れておくと便利です。そうすれば、「入力欄のすぐ下」に赤文字で警告を出したり、「画面の一番下」にまとめてエラーメッセージを表示したりといった操作が自由自在になります。コンテキストは単なるデータ置き場ではなく、アプリを賢く動かすための「司令塔」の役割も果たしてくれるのです。難しい言葉を使いましたが、要は「みんなが見る掲示板に、注意書きも一緒に書いておく」という感覚です。
7. すべてを組み合わせてアプリを完成させる
最後に、これまで作った部品を一つの画面にまとめます。ここで重要なのは、一番外側を `FormProvider` で包むことです。この包みの中にいれば、どんなに深い場所に置かれた部品でも、共有の箱を使う権利が与えられます。
これで、入力・表示・リセットが完璧に連動するフォームアプリの完成です。バケツリレーで苦労していた頃に比べると、コードが非常に読みやすく、後から項目を増やすのも簡単になっているはずです。リアクトのコンテキストを使いこなせれば、プロの開発者に大きく一歩近づいたと言えるでしょう。
import React from "react";
import { FormProvider } from "./FormContext";
import InputFields from "./InputFields";
import PreviewArea from "./PreviewArea";
import ResetButton from "./ResetButton";
function App() {
return (
<FormProvider>
<div className="container mt-5" style={{ maxWidth: "500px" }}>
<h1 className="text-center mb-4">お問い合わせフォーム</h1>
<InputFields />
<PreviewArea />
<div className="mt-3">
<ResetButton />
</div>
</div>
</FormProvider>
);
}
export default App;
8. コンテキストを使ったフォーム管理のメリット
今回学んだ方法には、大きなメリットが三つあります。一つ目は、部品の独立性です。入力する部品と表示する部品が完全に分かれているため、デザインの変更や機能の追加がとても楽になります。二つ目は、保守性です。データがどこで管理されているかが一目瞭然なので、後からプログラムを見直した時に迷うことがありません。
そして三つ目は、拡張性です。例えば、後から「郵便番号」の入力欄を追加したくなっても、共有の箱に一つ項目を足すだけで、アプリ全体の準備が整います。パソコンを使い慣れていない方にとって、プログラミングは難しく見えるかもしれませんが、このように「情報を整理するルール」を覚えることが上達への近道です。このコンテキストの力を借りて、自分だけの便利なツール作りに挑戦してみてください。