背景
大量の入力フォームをフロントエンドに実装する機会がありました。
React でひとつひとつ <input>
や <select>
を書いていくのは正直つらい。しかも、バリデーションや必須チェックを個別に実装していくとコード量が増え、メンテナンス性も落ちていきます。
そこで react-jsonschema-form (RJSF) を採用しました。
JSON Schema を書くだけでフォームを自動生成してくれるライブラリで、「フォームの定義」と「バリデーションルール」を一元化できる のが大きな特徴です。
この記事では、実際に RJSF をプロジェクトで使ってみて感じたことを、メリット・デメリット・学びという観点で振り返ってまとめます。
RJSFの概要
react-jsonschema-form(RJSF) は、JSON Schema をもとに自動でフォームを生成してくれる React のライブラリです。
特徴を一言でまとめると、「フォームの定義(項目・型・必須条件)を JSON Schema に書くだけで、UI とバリデーションが自動で動く」 という点です。
主要な特徴
-
自動フォーム生成
- Schema を渡すと、テキスト入力・数値入力・チェックボックス・ラジオボタンなどを自動生成します。
-
バリデーションの自動化
-
required
やtype: number
、enum
などの定義に基づいて、自動で入力チェックが行われます。
-
-
カスタマイズ性
-
uiSchema
を使うと、入力コンポーネントの種類や表示方法を制御可能。 - カスタムウィジェットを作成すれば、既存の UI ライブラリ(Material-UI, Ant Design など)と統合できます。
-
-
スキーマ駆動開発
- バックエンドと JSON Schema を共通化することで、入力ルールをフロントとサーバーで同期できます。
簡単なサンプル
import Form from "@rjsf/core";
const schema = {
title: "User",
type: "object",
required: ["name"],
properties: {
name: { type: "string", title: "Name" },
age: { type: "number", title: "Age" }
}
};
export default function App() {
return (
<Form
schema={schema}
onSubmit={({ formData }) => console.log("送信データ:", formData)}
/>
);
}
このコードを実行すると、Name
と Age
の入力欄が自動で生成され、name
が必須項目としてバリデーションされます。
「普通のフォーム」との違いをざっくり言うと、RJSFは「入力欄を自分で書く」のではなく、「Schemaを渡すだけで生成される」という点にあります。
実際の使い方
RJSF の使い方はシンプルで、JSON Schema を定義して <Form />
コンポーネントに渡す だけです。
基本的なフォーム定義
import Form from "@rjsf/core";
const schema = {
title: "ユーザー情報",
type: "object",
required: ["name"],
properties: {
name: { type: "string", title: "名前" },
age: { type: "number", title: "年齢" },
gender: {
type: "string",
title: "性別",
enum: ["male", "female", "other"]
}
}
};
export default function App() {
return (
<Form
schema={schema}
onSubmit={({ formData }) => console.log("送信データ:", formData)}
/>
);
}
これだけで以下の UI が自動生成されます。
- 名前(テキストボックス、必須)
- 年齢(数値入力)
- 性別(ドロップダウン、enum から選択)
onSubmit
を使えば、入力データを API に送ったり、state に保存できます。
UI をカスタマイズしたいとき(uiSchema)
Schema だけだと無骨なフォームになりがちなので、uiSchema
を追加して UI を制御します。
const uiSchema = {
age: {
"ui:widget": "updown" // 数値入力をスピンボックスにする
},
gender: {
"ui:widget": "radio" // ドロップダウンではなくラジオボタンにする
}
};
<Form schema={schema} uiSchema={uiSchema} />
こうすることで、ユーザーが直感的に入力しやすい UI に調整できます。
配列やネストにも対応
フォームが複雑になっても Schema を書くだけで対応可能です。
{
"type": "object",
"properties": {
"hobbies": {
"type": "array",
"title": "趣味",
"items": { "type": "string" }
}
}
}
RJSF は自動で「+ Add Item」ボタンを表示して、趣味をいくつでも追加できるフォームを生成します。
メリット・デメリットまとめ
良かった点
-
項目数が多くても破綻しない
50 項目以上のフォームでも、Schema に追記するだけで UI とバリデーションが同時に増えるため、普通のフォーム実装に比べて圧倒的に楽でした。 -
バリデーションが自動で効く
required
やtype
,minimum
,enum
などを Schema に書けばすぐに反映。
別ライブラリでルールを二重に書かなくて良いのは安心感がありました。 -
バックエンドと整合性が取りやすい
サーバー側でも JSON Schema を返す設計だったため、フロントと同じ定義を使えました。
「必須チェックが片方だけ違う」といったズレが起きにくいのは地味に効きます。
困った点
-
小規模フォームではオーバースペック
3〜5 項目程度のフォームだと、むしろ Schema を書く手間が増え、普通に<input>
を並べたほうが早いです。 -
デザイン調整に工夫が必要
デフォルトの UI だけでは物足りず、結局uiSchema
やカスタムウィジェットで調整が必要でした。
「自動生成」とはいえ、実務では UI/UX を考慮してカスタムすることが多かったです。 -
学習コスト
Schema の仕様に慣れるまでは「どう書けばドロップダウンになるのか?」「配列はどう扱うのか?」など調べる時間が必要でした。
学び・まとめ
普通に React でフォームを作ると、入力欄の実装・バリデーション・サーバーとの整合性をそれぞれ別々に管理する必要があります。
RJSF を導入したことで、それらを JSON Schema というひとつの定義に集約できる ようになり、大規模フォームでも安定して開発を進められました。
一方で、小規模フォームではオーバースペックになったり、UI のカスタマイズには工夫が必要だったりと、「とりあえず導入すれば万能」というわけではありません。
振り返りとしての学び
- 大規模で項目が多いフォームや、サーバーとルールを共有したいケースには非常に有効
- UI/UX の調整をどこまでカスタムするかを最初に決めておくとスムーズ
- Schema ベースの開発に慣れると、バックエンドとフロントの境界を明確にしつつ効率化できる
RJSF を使った今回の経験から、今後フォームを設計するときには
- 「このフォームは RJSF で効率化できるか?」
- 「それともシンプルに自前で書く方が早いか?」
を見極める判断力がついたと思います。
特に、設計段階で「フォームのスケール」を見積もることの重要性を学べたのは大きな収穫でした。