どうも、ノマドクリエイターのショウヘイ(@shohei_creator)です。
ブログアシスタントのふーちゃんです。
HTML で構成されるフォームに細かなバリデーションをかけるには、 JavaScript による DOM 操作が必須になります。バリデーション処理を実装する作業は手間が多いので、バリデーション用のライブラリを使う方法が現実的です。
React には、フォームにバリデーションを簡単に実装できる React Hook Form というライブラリが用意されています。 React Hook Form は、 Yup や Zod といったバリデーション特化ライブラリと連携できるため、とても拡張性が高いです。
この記事では、 React Hook Form の使い方について説明します。
この記事では、 React Hook Form の Version 7 の内容を取り扱います。
Version 6 以前では存在しなかったフックやメソッドが登場しているので、注意してください。
React Hook Form とは
React Hook Form とは、 React でフォームのバリデーションを実装するためのライブラリです。公式サイトでは、「高性能で柔軟かつ拡張可能な使いやすいフォームバリデーションライブラリ」と謳われています。
React Hook Form は、非制御コンポーネント (Uncontrolled Components) を useForm フックに登録( register) することで、フォームのフィールド情報を検証・収集できることをコンセプトに据えています。
制御コンポーネントと非制御コンポーネントの違い
React Hook Form の公式ドキュメントでは、制御・非制御コンポーネントの単語が何度も出てきます。ライブラリについての理解を深めるために、 制御・非制御コンポーネントの概要について触れておきます。
制御・非制御コンポーネントの違いは、フォームのフィールド値を『 React 側の state として保持する』か『そのフィールド自身で保持する』かです。フィールドの値を保持する管理元が異なります。
制御コンポーネント( Controlled Component )とは 、 React 側の state として、フォームのフィールド値を管理しているコンポーネントを意味します。 setState メソッドによってのみ、フィールド値を更新します。
state によってフィールド値を管理しやすくなりますが、頻繁に再レンダリングを引き起こしてしまうことが欠点です。
// 制御コンポーネントの具体例
import { useState } from "react";
export default function App() {
const [state, setState] = useState<string>("");
const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
alert("名前: " + state);
};
const handleChange = (e: React.FormEvent<HTMLInputElement>) => {
setState(e.currentTarget.value);
};
return (
<form onSubmit={handleSubmit}>
<label>
名前
<input type="text" value={state} onChange={(e) => handleChange(e)} />
</label>
<button>実行する</button>
</form>
);
}
非制御コンポーネント( Uncontrolled Component )とは 、フォームのフィールドそのもので値を保持します。 フィールドから値を取得するには、 useRef フックなどを使って、事前に参照を渡しておく必要があります。
フィールド値が必要になるたびに、参照先から値を取得する手間が欠点です。その代わり、 React による頻繁な再レンダリングを防げます。また、純粋な HTML に近いので、他のフレームワークなどにコードを移植しやすいです。
// 非制御コンポーネントの具体例
import { useRef } from "react";
export default function App() {
const input = useRef<HTMLInputElement>(null);
const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
alert("名前: " + input.current);
};
return (
<form onSubmit={handleSubmit}>
<label>
名前
<input type="text" ref={input} />
</label>
<button>実行する</button>
</form>
);
}
React Hook Form の環境構築
React で React Hook Form を使うには、まずは npm または yarn などの JavaScript パッケージマネージャーを利用して、 React Hook Form ライブラリをインストールします。
React でアプリ開発するフォルダのディレクトリにて、ターミナルのコンソールから下記のコマンドを実行してください。
// npm を使う場合
npm install react-hook-form
// yarn を使う場合
yarn install react-hook-form
これから、 React アプリのファイルを編集していきます。まだ手元に編集するアプリを用意していないなら、 create-react-app
コマンドを使って、任意のアプリ名で初期の環境構築をおこなってください。
// 通常版
npx create-react-app アプリ名
// TypeScript対応版
npx create-react-app アプリ名 --template typescript
React Hook Form の基本的な構文
React Hook Foom には、数多くの機能が搭載されています。最初から大量の機能を見せてしまうと、記事を読み進めることが大変になるでしょう。
まずは、基本的な構文の把握を優先して、なるべく機能性をそぎ落とした具体例を載せます。下の画像のような簡易フォームを作っていきます。
react-create-app
コマンドで生成された App.tsx ファイルを改変していきます。きれいに表示されるように、ちょっとした CSS ファイルも適用しています。
いったん、すべてのソースコードを掲載します。その後に、コードを分割して、 React Hook Form に関する各種の機能を説明を書いていきます。
import "./styles.css";
// react-hook-formから、useFormとSubmitHandlerをimport
// SubmitHandlerは、submitイベントに関する関数の型宣言に使う
import { useForm, SubmitHandler } from "react-hook-form";
// フォームの入力値についての型定義。useFormフックを書く時に使う。
type FormInput = {
name: string;
age: number;
};
export default function App() {
// useFormフックを使い、registerとhandleSubmitを取得する。
// registerは、フォームのフィールドを登録することで、バリデーションを機能させる。
// handleSubmitは、submitイベントの制御に関わる。
const { register, handleSubmit } = useForm<FormInput>();
// submitイベントが発生して、かつバリデーションが成功した場合に実行する関数。
// サンプルコードなので、入力値(data)をコンソール出力するだけの処理を用意。
const onSubmit: SubmitHandler<FormInput> = (data) => console.log(data);
return (
// handleSubmitの第1引数は、バリデーションを通った場合にのみ実行される。
<form onSubmit={handleSubmit(onSubmit)}>
<label>
名前
{/* registerの第1引数の文字列は、name属性の値としても利用される。 */}
{/* registerの第2引数には、バリデーションの種類を設定できる。 */}
{/* requiredにtrueを設定すると、入力必須の状態になる。 */}
<input {...register("name", { required: true })} />
</label>
<label>
年齢
<input type="number" {...register("age", { required: true })} />歳
</label>
<button>送信する</button>
</form>
);
}
まずは、冒頭で必要な機能をライブラリから import します。今回は、 useForm フックと SubmitHandler を使います。
useForm フックは、 register や handleSubmit など、 React Hook Form を利用するうえで必須になる機能を取り出すために使います。どの機能を取り出すかについては、分割代入で選別できます。
SubmitHandler は、 TypeScript で書く場合に必要になる型定義です。 submit イベントに関連して実行する関数の型宣言に使います。
import "./styles.css";
// react-hook-formから、useFormとSubmitHandlerをimport
// SubmitHandlerは、submitイベントに関する関数の型宣言に使う
import { useForm, SubmitHandler } from "react-hook-form";
次に、各所で使う型定義です。
// フォームの入力値についての型定義。useFormフックを書く時に使う。
type FormInput = {
name: string;
age: number;
};
そして、 App コンポーネントの return 文の前に書いている各種の変数です。
まずは、 useForm フックを使って、 register と handleSubmit を取り出します。 TypeScript で書く場合には、 useForm フックの直後に、フォームの入力値についての型を宣言しておきます。
onSubmit 関数は、 submit イベントの発生して、かつバリデーションが成功した場合に実行します。 TypeScript で書く場合には、 SubmitHandler に続けて、フォームの入力値についての型で宣言します。引数の data には、入力フォームの入力値ついてのオブジェクトが格納されています。
export default function App() {
// useFormフックを使い、registerとhandleSubmitを取得する。
// registerは、フォームのフィールドを登録することで、バリデーションを機能させる。
// handleSubmitは、submitイベントの制御に関わる。
const { register, handleSubmit } = useForm<FormInput>();
// submitイベントが発生して、かつバリデーションが成功した場合に実行する関数。
// サンプルコードなので、入力値(data)をコンソール出力するだけの処理を用意。
const onSubmit: SubmitHandler<FormInput> = (data) => console.log(data);
return (
{/* 途中省略 */}
最後に、 return 文の中身です。主役となるフォームに関するタグが含まれています。
まずは、 form タブの onSubmit のイベントハンドラーとして、 handleSubmit(onSubmit) を設定します。 handleSubmit メソッドは、第 1 引数の関数を『バリデーションが成功した場合』に実行します。つまり、バリデーションが失敗した場合には、 onSubmit 関数は実行されないままになります。
input タグや select タグなどのフィールドには、 register をつけます。 この register によって、 React Hook Form でフィールド情報を管理できるようになります。
register の第 1 引数の文字列は、そのフィールドの name 属性値にも使われます。第 2 引数には、オブジェクト形式でバリデーションの種類を書き加えます。これにより、そのフィールドの入力値ついてバリデーションを実行できます。
return (
// handleSubmitの第1引数は、バリデーションが成功した場合にのみ実行される。
<form onSubmit={handleSubmit(onSubmit)}>
<label>
名前
{/* registerの第1引数の文字列は、name属性の値としても利用される。 */}
{/* registerの第2引数には、バリデーションの種類を設定できる。 */}
{/* requiredにtrueを設定すると、入力必須の状態になる。 */}
<input {...register("name", { required: true })} />
</label>
<label>
年齢
<input type="number" {...register("age", { required: true })} />歳
</label>
<button>送信する</button>
</form>
);
以上のファイル構成により、このような簡易フォームが出来上がります。フィールドに値が設定されている場合に送信するボタンを押すと、コンソールログが出力されることが確認できます。
React Hook Form でエラーメッセージを表示する方法
React Hook Form にはバリデーション機能が搭載されているので、もちろん、エラーメッセージの表示に関する便宜も図られています。 useForm フックの分割代入で formSate: {errors}
を設定しておくと、任意のエラーメッセージを表示できるようになります。
先ほどの基本構文に改変を加えて、バリデーションが失敗する場合にエラーメッセージが表示される仕様にしました。
それぞれのフィールドは、入力必須になっています。また、年齢の入力欄は、入力範囲を 0~150 に制限しています。
エラーメッセージはプレーンテキストとして表示されます。
CSS ファイルでクラス名と CSS プロパティを定義しておいて、エラーメッセージの CSS を適用してあげると、それっぽい見た目になりますよ。
import "./styles.css";
import { useForm, SubmitHandler } from "react-hook-form";
type FormInput = {
name: string;
age: number;
};
export default function App() {
const {
register,
handleSubmit,
formState: { errors }
} = useForm<FormInput>();
const onSubmit: SubmitHandler<FormInput> = (data) => console.log(data);
return (
<form onSubmit={handleSubmit(onSubmit)}>
<label>
名前
<input {...register("name", { required: true })} />
</label>
{/* 未入力の場合は、バリデーションが失敗してエラーになる */}
{/* erros.nameが値が入る(undefind)ので、右辺のpタグが評価される */}
{errors.name && <p className="error">名前欄の入力は必須です</p>}
<label>
年齢
<input
type="number"
{...register("age", {
// バリデーションごとにエラーメッセージを設定する場合は、オブジェクト形式でvalueとmessageを設定する
required: { value: true, message: "年齢欄の入力は必須です" },
min: { value: 0, message: "入力できる最小値は0です" },
max: { value: 150, message: "入力できる最大値は150です" }
})}
/>
歳
</label>
{/* errors.age.messageを参照すると、バリデーションが失敗した項目のメッセージが取得できる */}
{errors.age && <p className="error">{errors.age.message}</p>}
<button>送信する</button>
</form>
);
}
label {
display: block;
margin-bottom: 10px;
}
label input {
width: 100%;
max-width: 100px;
margin-left: 10px;
margin-right: 10px;
}
.error {
color: red;
margin-bottom: 20px;
}
React Hook Form でフィールドに初期値を一括で設定する方法
React Hook Form の useForm フックの 1 つに、 defaultValues があります。 defaultValues に引数としてオブジェクト( key は、フィールドの name 属性値)を設定すると、それぞれのフォームに初期値を与えられます。
エラーメッセージを追加したコードに対して、 useForm フックに defaultValues オプションを追加した場合の具体例を用意しました。
ブラウザにフォームが表示された時点で、すでにフィールド値が入力されていることを確認してください。
import "./styles.css";
import { useForm, SubmitHandler } from "react-hook-form";
type FormInput = {
name: string;
age: number;
};
export default function App() {
const {
register,
handleSubmit,
formState: { errors }
} = useForm<FormInput>(
// 初期値として、名前の入力欄に「山田太郎」・年齢の入力欄に「25」を与える
{ defaultValues: { name: "山田太郎", age: 25 } });
const onSubmit: SubmitHandler<FormInput> = (data) => console.log(data);
return (
<form onSubmit={handleSubmit(onSubmit)}>
<label>
名前
<input {...register("name", { required: true })} />
</label>
{errors.name && <p className="error">名前欄の入力は必須です</p>}
<label>
年齢
<input
type="number"
{...register("age", {
required: { value: true, message: "年齢欄の入力は必須です" },
min: { value: 0, message: "入力できる最小値は0です" },
max: { value: 150, message: "入力できる最大値は150です" }
})}
/>
歳
</label>
{errors.age && <p className="error">{errors.age.message}</p>}
<button>送信する</button>
</form>
);
}
React Hook Form の useForm フックの詳細
React Hook Form の useForm フックには、豊富なオプションが用意されています。
また、 useForm フックによって取得できる各メソッドにも、いくつかのオプションが用意されています。
それぞれの機能について、大まかに説明していきますね。
useForm フックのオプション一覧
React Hook Form の useForm フックの基本形は、以下のとおりです。必要に応じて、オプションを付け外ししてください。
// フォームの入力値についての型定義
type FormInputType = {
exampleInput1: string;
sexampleInput2: number;
exampleInput3: boolean;
}
const { method1, method2, method3 } = useForm<FormInputType>({
mode: 'onSubmit',
reValidateMode: 'onChange',
defaultValues: {},
resolver: undefined,
context: undefined,
criteriaMode: "firstError",
shouldFocusError: true,
shouldUnregister: false,
delayError: undefined
})
mode
mode は、どのイベントに紐づけて入力値のバリデーションを実行するのかを設定できます。初期値は、 onSubmit です。
- onSubmit
- input ( type 属性が submit )か、または button をクリックした時の submit イベントに紐づいて、バリデーションを実行する。
- onBlur
- フィールドのフォーカス状態が外れた時の bulr イベントに紐づいて、バリデーションを実行する。
- onChange
- フィールドの値に変化があった時の change イベントに紐づいて、バリデーションを実行する。
- onTouched
- 最初の blur イベントが発生した後に、 change イベントが発生するたびに、バリデーションを実行する。
- all
- blur イベントと change イベントに紐づいて、バリデーションを実行する。おそらく、 submit イベントも対象。
reValidateMode
reValidateMode は、 submit イベント後の初回バリデーションが実行された後に、フィールドの値に不備があってバリデーションが失敗した場合に、次にバリデーションを実行する時点を指定できます。初期値は、 onChange です。
- onChange
- フィールドの値に変化があった時の change イベントに紐づいて、バリデーションを実行する。
- onBlur
- フィールドの値のフォーカス状態が外れた時の bulr イベントに紐づいて、バリデーションを実行する。
- onSubmit
input[type="submit"]
か、またはbutton
の要素をクリックした時の submit イベントに紐づいて、バリデーションを実行する。
defaultValues
defaultValues は、初回レンダリング時におけるフィールドの初期値として利用されます。
フィールドには、空文字や null など、何かしらの初期値を設定しておくことが推奨されています。もしも、フィールドのタグ内部に初期値が設定されている場合には、 defaultValues の方が優先されます。
resolver
resolver は、 Yup ・ Zod ・ Joi ・ Superstruct ・ Vest などのバリデーションに関する外部ライブラリの導入に関するオプションです。
resolver オプションの外部ライブラリごとの実装方法は、一概には説明できません。
React Hook Form の公式ドキュメントの useForm ページに具体例が用意されているので、そちらを参照してください。
context
context オブジェクトは、変更可能です。 context は、 resolver の第 2 引数や Yup バリデーションの context オブジェクトとして使われます。
React Hook Form にバリデーション用の外部プラグインを導入しないなら、 context オブジェクトを使う機会は無いでしょう。
criteriaMode
criteriaMode は、バリデーションの失敗によるエラー(入力値が誤っている)の収集の程度を決められます。
初期値の firstError は、フォーム内で最初にバリデーションが失敗したフィールドのエラーを集めます。
all の場合は、フォーム内で バリデーションが失敗した全てのフィールドのエラーを集めます。
shouldFocusError
shouldFocusError は、バリデーションが失敗したフィールドに対する自動フォーカスの設定です。初期値の true は、バリデーションが失敗した最初のフィールドに自動フォーカスします。
shouldUnregister
React Hook Form では、アンマウントなどによってフィールドそのものが削除されても、 register の機能によって、入力値そのものは保持されます。
shouldUnregister は、 register の機能の活性を変更できます。初期値の false の場合は、 register によって入力値が保持されます。
shouldUnregister に true を設定した場合には、アンマウントによって入力欄が削除されると、 register から入力欄の登録を削除します。
delayError
delayError は、『バリデーションの失敗によるエラー状態の表示』をミリ秒単位で遅延させられます。
なお、 delayError は、エラー状態が継続する場合に適用されます。フィールドの値を修正してエラーが解消された場合には、遅延することなく、即座にエラー状態が解除されます。
shouldUseNativeValidation
shouldUseNativeValidation は、 React Hook Form のフォームをネイティブなフォーム(つまり、 HTML を書いて作る通常のフォーム)のような挙動に変更できます。これにより、 :valid
や :invalid
といった CSS セレクターが使えるようになり、 CSS によってフィールドの見た目を変更できます。
shouldUseNativeValidation の初期値は、 false です。
register メソッドの概要
useForm フックの resister メソッドは、 React Hook Form に input タグや select タグなどのフィールドを登録することで、フィールド情報を管理したり、任意のバリデーションを実行出来たりします。
register メソッドの第 1 引数に設定する文字列は、フィールドの name 属性値として使われます。一意な文字列にする必要があるので、注意してください。また、第 1 引数は、数字から始まったり、数字だけであったりしてはいけません。
register メソッドは、第 2 引数の設定内容によって、バリデーションとエラーメッセージについての挙動を変更できます。
ref
ref は、 register にフィールドを登録します。また、 ref の文字列は、フィールドの name 属性の値ともなります。
ref を使う時には、これといって「 ref 」の文字を書く必要はありません。 register メソッドの第 1 引数に文字列を設定すれば、それが ref として扱われます。 register メソッドを使う時は、ほぼ確実に ref を書くことになります。
<input {...register("fieldName")} />
required
required は、フォームのフィールドに対する値の入力・選択の必須化を設定できます。 required に true を設定すると、必須化の状態になります。
// バリデーションのみの場合
<input
{...register("fieldName", {
required: true
})}
/>
// バリデーションに対応するエラーメッセージも登録する場合
<input
{...register("fieldName", {
required: "error message"
})}
/>
maxLength
maxLength は、 フィールドの入力値( string 型)の文字数の上限を設定できます。もしも、上限を上回る文字数が入力された場合には、バリエーションが失敗します。
// バリデーションのみの場合
<input
{...register("fieldName", {
maxLength: 2
})}
/>
// バリデーションに対応するエラーメッセージも登録する場合
<input
{...register("fieldName", {
maxLength : {
value: 2,
message: "error message"
}
})}
/>
minLength
minLength は、 フィールドの入力値( string 型)の文字数の下限を設定できます。もしも、下限を下回る文字数が入力された場合には、バリエーションが失敗します。
// バリデーションのみの場合
<input
{...register("fieldName", {
minLength: 1
})}
/>
// バリデーションに対応するエラーメッセージも登録する場合
<input
{...register("fieldName", {
minLength: {
value: 1,
message: "error message"
}
})}
/>
max
max は、 フィールドの入力値( number 型)の上限を設定できます。もしも、上限を上回る値が入力された場合には、バリエーションが失敗します。
// バリデーションのみの場合
<input
type="number"
{...register("fieldName", {
max: 3
})}
/>
// バリデーションに対応するエラーメッセージも登録する場合
<input
type="number"
{...register("fieldName", {
max: {
value: 3,
message: "error message"
}
})}
/>
min
min は、入力値( number 型)の下限を設定できます。もしも、下限を下回る値が入力された場合には、バリエーションが失敗します。
// バリデーションのみの場合
<input
type="number"
{...register("fieldName", {
min: 3
})}
/>
// バリデーションに対応するエラーメッセージも登録する場合
<input
type="number"
{...register("fieldName", {
min: {
value: 3,
message: "error message"
}
})}
/>
pattern
pattern は、フィールドの値に対して正規表現による判定をおこなえます。もしも、正規表現に合わない入力値の場合には、バリエーションが失敗します。
// バリデーションのみの場合
<input
{...register("fieldName", {
pattern: /[A-Za-z]{3}/
})}
/>
// バリデーションに対応するエラーメッセージも登録する場合
<input
{...register("fieldName", {
pattern: {
value: /[A-Za-z]{3}/,
message: "error message"
}
})}
/>
validate
validate は、引数として比較演算子などを含む関数を渡すことで、フィールドの値が条件を満たしているかどうか判定できます。複数の条件でバリデーションを実行したい場合には、複数の関数をオブジェクト形式にまとめてください。
// バリデーションのみの場合
// 単体の関数でバリデーションする場合
<input
{...register"fieldName", {
validate: value => value === "1"
})}
/>
// 複数の関数でバリデーションする場合
<input
{...register("fieldName", {
validate: {
positive: v => parseInt(v) > 0,
lessThanTen: v => parseInt(v) < 10,
checkUrl: async () => await fetch(),
}
})}
/>
// バリデーションに対応するエラーメッセージも登録する場合
// 単体の関数でバリデーションする場合
<input
{...register("fieldName", {
validate: value => value === "1" || "error message"
})}
/>
// 複数の関数でバリデーションする場合
<input
{...register("fieldName", {
validate: {
positive: v => parseInt(v) > 0 || "error message",
lessThanTen: v => parseInt(v) < 10 || "serror message",
checkUrl: async () => await fetch() || "error message"
}
})}
/>
disabled
disabled は、フォームのフィールドの活性・非活性を制御できます。 disabled に true を設定した場合には、入力値が不定として扱われ、 フィールドの入力制御が無効な状態になります。
<input
{...register("fieldName", {
disabled: true
})}
/>
onChange ・ onBlur
フォームのフィールドに対する onChange イベントまたは onBlur イベントに、任意の関数の実行を紐づけられます。
register("fieldName", {
onChange: (e) => console.log(e)
})
register("fieldName", {
onBlur: (e) => console.log(e)
})
value
value は、フォームのフィールドに任意の入力値を設定します。
register("fieldName", { value: "example value" })
shouldUnregister
shouldUnregister は、フォームのフィールドがアンマウントされる時に、 register からフィールドの登録を削除できます。
<input
{...register("fieldName", {
shouldUnregister: true,
})}
/>
unregister メソッドの概要
unregister メソッドは、 register メソッドを使って登録したフィールドの情報を削除できます。また、そのフィールドに関する入力値とバリデーションルールも削除されます。
なお、 unregister メソッドの第 2 引数にオプションを設定すると、 フォームのフィールドの情報を削除されても、オプションに対応する値が保持されるようになります。
unregister メソッドを使って単体のフィールドの登録を削除する場合は、引数として、 register メソッドで使った登録名(フィールドの name 属性値)を設定します。複数のフィールドの登録をまとめて削除する場合は、引数として、登録名を要素に持つ配列を設定します。
// 単体のフィールドの登録を削除する場合
unregister("fieldName");
// 複数のフィールドの登録をまとめて削除する場合
unregister(["fieldName", "fieldName2"]);
外部プラグインによるバリデーションルールを導入していた場合には、 unregister メソッドによってフィールドを削除しても、そのフィールドに関するバリデーションルールは残ります。
const schema = yup.object().shape({
fieldName: yup.string().required()
}).required();
// fieldNameの登録を削除しても、YupのfieldNameに対するバリデーションルールは残る
unregister("fieldName");
unregister メソッドを使う時には、内部に register メソッドを持つフィールドが再マウントされないようにコードを書いてください。
const [show, setShow] = React.useState(true)
const onClick = () => {
unregister("fieldName");
// showがtrueのままだと、またfieldNameがregisterメソッドで登録されてしまう
// showをfalseにすることで、<input {...register('fieldName')} />が評価されないようにする。
setShow(false);
}
// showがtrueの場合には、右辺が評価されて、fieldNameがregisterメソッドによって登録される。
{show && <input {...register("fieldName")} />}
keepDirty
keepDirty は、 true に設定すると、 formState メソッドの isDirty と dirtyFields の状態を保持します。
unregister("fieldName",
{ keepDirty: true }
)
keepTouched
keepTouched は、 true に設定すると、フィールドの登録を削除した後に、その入力の状態を削除しなくなります。
unregister("fieldName",
{ keepTouched: true }
)
keepValid
keepDirty は、 true に設定すると、 フィールドの登録を削除しても、 isValid の状態は保持されます。
unregister("fieldName",
{ keepValid: true }
)
keepError
keepError は、 true に設定すると、 フォームのフィールドのエラー情報が保持されます。
unregister("fieldName",
{ keepError: true }
)
keepValue
keepValue は、 true に設定すると、 フォームのフィールドの現在の値が保持されます。
unregister("fieldName",
{ keepValue: true }
)
keepDefaultValue
keepDefaultValue は、 true に設定すると、 useForm フックで定義したフィールドの初期値が保持されます。
unregister("fieldName",
{ keepDefaultValue: true }
)
formState オブジェクトの概要
formState オブジェクトは、フォーム内の各種フィールド state (変数の状態)を保持しています。 state を参照したい場合は、 useForm フックを使う時に、 formState オブジェクトの値として、対象の state 名を書いておく必要があります。
const { formState: { errors, isDirty, isSubmitting, touchedFields, submitCount } } = useForm();
もしも、 useEffect フックの中で formState オブジェクトを使う場合には、依存配列に formState そのものを設定するようにしてください。
useEffect(() => {
if (formState.errors.fieldName) {
// 何かしらの処理
}
// 依存配列には、「formState」そのものを設定
// 「formState.errors.fieldName」の設定は、NG
}, [formState]);
- isDirty
- フォーム内のどれか 1 つでもフィールドの値に変更があると、 true に更新されます。
- dirtyFields
- ユーザーによって値が変更された全てのフィールド情報を持つオブジェクトです。フィールドの変更を検知する都合により、 useForm フックの defaultValues によって初期値が与えられている状態が好ましいです。
- touchedFields
- ユーザーによって操作された全てのフィールド情報を持つオブジェクトです。
- isSubmitted
- フォームの内容が submit イベントによって送信された時に、 true に更新されます。 reset メソッドが実行されるまでは、 true の状態が継続します。
- isSubmitSuccessful
- フォームにて submit イベントが起きた時に、 handleSubmit によって何かしらのエラーが検出されることなく、フォームの内容が正常に送信された場合に、 true に更新されます。
- isSubmitting
- フォームの内容が送信されている最中は true 、それ以外は false になります。
- submitCount
- フォームが送信された回数を保持しています。
- isValid
- フォームのフィールドに対して、バリデーションによるエラーがなければ、 true になります。
- isValidating
- フォームのフィールドにバリデーションを実行している最中は、 true になります。
- errors
- フォームのフィールドにバリデーションを実行した時のエラーを持つオブジェクトです。
watch メソッドの概要
watch メソッドは、引数として設定したフィールドの状態を監視して、入力値を返します。
watch メソッドは、 register メソッドよりも前に呼び出されます。そのため、 useForm フックなどを介してフィールドに初期値が与えられていない場合には、 undefined を返します。
watch メソッドの挙動により、アプリまたはフォームは、ルートディレクトリから再レンダリングされます。レンダリング回数を減らしてパフォーマンスを改善したい場合には、コールバックの手法を使うか、または useWatch フックを利用してください。
watch メソッドに対する引数の設定方法は、いくつかの種類があります。
// registerメソッドの登録名を単体で設定する場合
const watchField= watch("fieldName");
// 第2引数も設定した場合は、第2引数は初期値として使われる
const watchField= watch("fieldName", defaultValue);
// registerメソッドの登録名を配列で設定する場合
const watchFields= watch(["fieldName", "fieldName2"]);
// watchメソッドに引数を設定しない場合
// registerメソッドに登録されている全てのフィールドが監視対象になる
const watchFields = watch();
handleSubmit メソッドの概要
handleSubmit メソッドは、バリデーションの成否によって、引数に渡した関数(コールバック関数)の実行を振り分けられます。
handleSubmit メソッド の第 1 引数のコールバック関数は、フォームのフィールドに対する全てのバリデーションが成功した合にみ、実行されます。一方、第 2 引数にコールバック関数は、フィールドのバリデーションがどれか 1 つでも失敗した場合に、実行されます。
TypeScript で書く場合は、コールバック関数の props 型の宣言用に、 SubmitHandler と SubmitErrorHandler が用意されています。
import "./styles.css";
import { useForm, SubmitHandler, SubmitErrorHandler } from "react-hook-form";
type FormInput = {
lastName: string;
firstName: string;
};
export default function App() {
const {
register,
handleSubmit,
formState: { errors }
} = useForm<FormInput>();
// バリデーションが成功した場合に実行。dataには、バリデーションが成功したフィールド情報が含まれている。
const success: SubmitHandler<FormInput> = (data) => console.log(data);
// バリデーションが失敗した場合に実行。errosには、バリデーションが失敗したフィールド情報が含まれている。
const error: SubmitErrorHandler<FormInput> = (erros) => console.log(erros);
return (
<form onSubmit={handleSubmit(success, error)}>
<label>
姓
<input
{...register("lastName", {
required: { value: true, message: "名の入力は必須です" }
})}
/>
</label>
{errors.lastName && <p className="error">{errors.lastName.message}</p>}
<label>
名
<input
{...register("firstName", {
required: { value: true, message: "名の入力は必須です" }
})}
/>
</label>
{errors.firstName && <p className="error">{errors.firstName.message}</p>}
<button>送信する</button>
</form>
);
}
reset メソッドの概要
reset メソッドは、フォームの複数フィールドの状態をまとめてリセットします。第 1 引数には、リセットに使うオブジェクト(登録名と値のプロパティ)を設定します。第 2 引数には、オプションとして、リセットから除外したい対象を指定できます。
- keepErrors
- true を設定すると、フィールドのバリデーションエラーを残します。
- keepDirty
- true を設定すると、 DirtyFields の状態は残ります。また、 isDirty の状態は、ユーザーからの操作があるまで、一時的に現在のものが使われます。
- keepValues
- true を設定すると、フィールドの値を残します。
- keepDefaultValues
- true を設定すると、 useForm フックを経由して初期値によってリセットします。
- isDirty は、もともとの defaultValues と比較によって、再び評価されます。
- dirtyFields は、もともとの defaultValues に対して、ルートレベルに限定して評価されると、再び更新されます。
- keepIsSubmitted
- true を設定すると、 isSubmitted の状態を残します。
- keepTouched
- true を設定すると、 isTouched の状態を残します。
- keepIsValid
- true を設定すると、 isValid の状態は、ユーザーから追加の操作があるまで、一時的に現在のものが使われます。
- keepSubmitCount
- true を設定すると、 submitCount の状態を残します。
resetField メソッドの概要
resetField メソッドは、フォームの個々のフィールドの状態をリセットします。第 1 引数には、リセットに使う値を設定します。第 2 引数には、オプションとして、リセットから除外したい対象を指定できます。
- keepError
- true を設定すると、フィールドのバリデーションエラーを残します。
- keepDirty
- true を設定すると、 DirtyFields の状態は残ります。また、 isDirty の状態は、ユーザーからの操作があるまで、一時的に現在のものが使われます。
- keepTouched
- true を設定すると、フィールド値を残します。
- defaultValue
- フィールドに値が入力されていない場合は、代わりに defaultValue が設定されます。
setError メソッド概要
setError メソッドは、意図的に 1 つ以上のエラーを発生させられます。
setError メソッドは 、フィールドの入力値がバリデーションに成功した場合は、関連する入力エラーを永続化できません。フィールドに関連付けられていないエラーは、 clearErros メソッドによってクリアされるまで永続化します。
フィールドの入力が無効な状態になっている場合は、 shouldFocus は機能しません。
// 単体のエラーを発生させる場合
setError("fieldName", {type: "manual", message: "error message"});
// 複数のエラーを発生させる場合
setError("fieldName", {types: {required: "error message", minLength: "error message"}});
clearErrors メソッドの概要
clearErrors メソッドは、フォームのフィールドに対するバリデーションエラーを消去できます。
clearErrors メソッドには、引数に設定方法によって、 バリデーションエラーを消去するフィールドが変わります。
// すべてのフィールドのバリデーションエラーを消去
clearErrors();
// 登録名に紐づいているフィールドのバリデーションエラーを消去
clearErrors("firstName");
//要素である登録名に紐づいているフィールドのバリデーションエラーをまとめて消去
clearErrors(["firstname", "lastName"]);
setValue メソッドの概要
setValue メソッドは、 register メソッドによって登録されているフィールドに対して、動的に値を設定できます。第 1 引数には、 register メソッドに登録した登録名を設定します。また、第 2 引数には、更新する値を設定します。
setValue("name", "value")
setValue メソッドを使って値を更新する時に、以下の条件に当てはまらなければ、再レンダリングは起きません。
- バリデーションが失敗する。
- バリデーションが成功して、エラーが解消される。
- setValue メソッドがはじめて実行されて、 formState の isDirty が true に切り替わる。
setValue メソッドに値を設定する時に、第 3 引数に { shouldValidate: true }
を設定すると、バリデーションを実行できます。
setValue("name", "value", { shouldValidate: true })
setValue メソッドに値を設定する時に、第 3 引数に { shouldDirty: true }
を設定すると、値の設定によってフィールドの状態を dirty にできます。
setValue("name", "value", { shouldDirty: true })
setValue メソッドに値を設定する時に、第 3 引数に { shouldTouch: true }
を設定すると、値の設定によって フィールド を touch した状態にできます。
setValue("name", "value", { shouldTouch: true })
setFocus メソッドの概要
setFocus メソッドは、対象のフィールドに自動フォーカスを実行します。このメソッドを機能させるには、 register メソッドを使って、フィールドを登録しておく必要があります。
setFocus メソッドは、 useEffeft フックや特定のイベントに紐づけて使われることが多いです。
<button
type="button"
onClick={() => clearErrors("fieldName")}
>
getValues メソッドの概要
getValues メソッドは、フォームからフィールドの値を読み取るために最適化されたヘルパー機能です。 watch メソッドと異なり、再レンダリングが起動することがなく、また入力の変化を監視しません。
getValues メソッドには、引数に設定方法によって、得られるフィールドの値が変わります。引数に何も設定しない場合は、 register メソッドに登録されている全てのフィールドの値を取得できます。引数に登録名を設定すると、その登録名に紐づているフィールドの値を取得できます。
import { useForm } from "react-hook-form";
import "./styles.css";
type FormInputs = {
fieldName: string;
fieldName2: string;
};
export default function App() {
const { register, getValues } = useForm<FormInputs>();
const getValue = () => {
// 引数を設定しない場合は、すべてのフィールド情報を取得
const values = getValues();
console.log(values);
// 指定したフィールドの値を取得
const singleValue = getValues("fieldName");
console.log(singleValue);
// 指定した複数フィールドの値を配列として取得
const multipleValues = getValues(["fieldName", "fieldName2"]);
console.log(multipleValues);
};
return (
<form>
<label>
入力欄1
<input {...register("fieldName")} />
</label>
<label>
入力欄2
<input {...register("fieldName2")} />
</label>
<button type="button" onClick={getValue}>
フィールドの値を取得する
</button>
</form>
);
}
trigger メソッドの概要
trigger メソッドは、引数に register メソッドに登録した登録名を設定することで、フォームのフィールドに対するバリデーションを意図的に実行できます。
trigger メソッドの使い道は、何かしらの要素の click イベントや change イベントで実行する処理の一部として組みこまれることが多いです。
import { useForm } from "react-hook-form";
import "./styles.css";
type FormInputs = {
fieldName: string;
fieldName2: string;
fieldName3: string;
};
export default function App() {
const {
register,
trigger,
formState: { errors }
} = useForm<FormInputs>();
return (
<form>
<label>
フィールド1
<input
{...register("fieldName", {
required: { value: true, message: "フィールド1の入力は必須です" }
})}
/>
</label>
{errors.fieldName && <p className="error">{errors.fieldName.message}</p>}
<label>
フィールド2
<input
{...register("fieldName2", {
required: { value: true, message: "フィールド2の入力は必須です" }
})}
/>
</label>
{errors.fieldName2 && (
<p className="error">{errors.fieldName2.message}</p>
)}
<label>
フィールド3
<input
{...register("fieldName3", {
required: { value: true, message: "フィールド3の入力は必須です" }
})}
/>
</label>
{errors.fieldName3 && (
<p className="error">{errors.fieldName3.message}</p>
)}
<button
type="button"
onClick={() => {
trigger("fieldName");
}}
>
1つ目のフィールドの検証
</button>
<button
type="button"
onClick={() => {
trigger(["fieldName", "fieldName2"]);
}}
>
1つ目と2つ目のフィールドの検証
</button>
<button
type="button"
onClick={() => {
trigger();
}}
>
Trigger All
</button>
</form>
);
}
control オブジェクトの概要
control オブジェクトには、 React Hook Form に対してコンポーネントを登録するメソッドが含まれています。コンポーネントの props として control オブジェクトを渡すとことで、そのコンポーネントを React Hook Form の管理下におけます。
外部ライブラリの UI コンポーネントを導入する時に、 Controller タグの props として使われることが多いです。
import { useForm, Controller } from "react-hook-form";
import { TextField } from "@material-ui/core";
type FormInputs = {
fieldName: string;
};
export default function App() {
const { control, handleSubmit } = useForm<FormInputs>();
const onSubmit = (data: FormInputs) => console.log(data);
return (
<form onSubmit={handleSubmit(onSubmit)}>
<Controller
name="fieldName"
// propsとしてcontrolオブジェクトを渡す
control={control}
render={({ field: { onChange, value, ref } }) => (
<TextField onChange={onChange} value={value} />
)}
/>
<button>送信する</button>
</form>
);
}
React Hook Form の useController フックの詳細
useController フックは、 Controller コンポーネントの機能を扱いやすいようにフック化したものです。コンポーネント内部でフックを利用できるので、フィールドタグを内包したコンポーネントを再利用しやすくなります。
- name
- Controller タグの内部にあるフィールドにつける一意の名前です。
- control
- useForm フックによって取得できる control オブジェクトです。 FormProvider を使う時は、オプションとして扱われます。
- render
- React 要素を返却したり、コンポーネントにイベント情報や値を渡したりする関数です。 React Hook Form と『非標準の props 名を持つ外部の制御コンポーネント』の統合が簡単になります。
- defaultValue
- 意味合いは、非制御コンポーネントの初期値と同じです。真偽値を渡す場合は、チェックボックスの入力として認識されます。
rules={{ required: true }}
- rules
- register メソッドと同じバリデーションルールを設定できます。
- shouldUnregister
- Controller コンポーネント内のフィールドがアンマウトされると、 regeister の登録状態から削除します。初期値( defaultValues )も、同様に削除されます。
- field
- onChange
- React Hook Form に、フィールドの入力値を渡します。フィールドの onChange 属性に割り当てる必要があります。
- onBlur
- React Hook Form に、フィールドに関する onBlur イベントを渡します。フィールドの onBlur 属性に割り当てる必要があります。
- value
- フィールドの現在の入力値です。
- name
- フィールドの名前です。
- ref
- React Hook Form とフィールドを接続するためのものです。 React Hook Form がエラー検知できるように、フィールドに ref 属性値を割り当てます。
- onChange
- fieldState
- invalid
- フィールドの現在の入力値に対するバリデーションの結果です。
- isTouched
- フィールドが操作されたかどうかの状態です。
- isDirty
- フィールドに値に何か変更があった場合には、 true に更新されます。
- error
- フィールドのエラー情報を持つオブジェクトです。
- invalid
- formState
- isSubmitSuccessful
- フォーム内の情報の送信に成功した場合には、 true に更新されます。
- isDirty
- フォーム内のフィールドについて、どれか 1 つでも値が変更された場合には、 true になります。
- isSubmitted
- フォームで submit イベントが起きると、 true に更新されます。 reset メソッドが使われない限りは、 true の状態が維持されます。
- dirtyFields
- ユーザーによって値が変更されたフィールドをプロパティとするオブジェクトです。 React Hook Form がフィールド値と初期値を比較できるように、 useForm フックを経由して初期値が与えられることが重要になります。
- touchedFields
- ユーザーによって操作されたフィールドをプロパティとするオブジェクトです。
- isSubmitting
- フォーム内の情報が送信されている最中は、 true に更新されます。それ以外の場合は、 false でう。
- submitCount
- フォームで submit イベントが起きた回数を保持します。
- isValid
- フォーム内の全てのフィールドでバリデーションが成功した場合に、 true に更新されます。
- isValidating
- フォーム内のフィールドに対してバリデーションが実行されている場合には、 true に更新されます。それ以外は、 false です。
- isSubmitSuccessful
Controller コンポーネント
本来、 React Hook Form は、非制御コンポーネントやネイティブな HTML フォームを使うことを前提にしています。
しかし、外部ライブラリ( React-Select や Mateial-UI など)の UI コンポーネントを導入できないと不便です。そこで、そういった UI コンポーネントに対して React Hook Form を提供するためのラッパーコンポーネントとして、 Controller コンポーネントが用意されています。
- name
- Controller タグの内部にあるフィールドにつける一意の名前です。
- control
- useForm フックによって取得できる control オブジェクトです。 FormProvider を使う時は、オプションとして扱われます。
- render
- React 要素を返却したり、コンポーネントにイベント情報や値を渡したりする関数です。 React Hook Form と『非標準の props 名を持つ外部の制御コンポーネント』の統合が簡単になります。
- defaultValue
- 意味合いは、非制御コンポーネントの初期値と同じです。真偽値を渡す場合は、チェックボックスの入力として認識されます。
rules={{ required: true }}
- rules
- register メソッドと同じバリデーションルールを設定できます。
- shouldUnregister
- Controller コンポーネント内のフィールドがアンマウトされると、 regeister の登録状態から削除します。初期値( defaultValues )も、同様に削除されます。
- field
- onChange
- React Hook Form に、フィールドの入力値を渡します。フィールドの onChange 属性に割り当てる必要があります。
- onBlur
- React Hook Form に、フィールドに関する onBlur イベントを渡します。フィールドの onBlur 属性に割り当てる必要があります。
- value
- フィールドの現在の値です。
- name
- フィールドの名前です。
- ref
- React Hook Form とフィールドを接続するためのものです。 React Hook Form がエラー検知できるように、フィールドに ref 属性値を割り当てます。
- onChange
- fieldState
- invalid
- フィールドの現在の入力値に対するバリデーションの結果です。
- isTouched
- フィールドが操作されたかどうかの状態です。
- isDirty
- フィールドに値に何か変更があった場合には、 true に更新されます。
- error
- フィールドのエラー情報を持つオブジェクトです。
- invalid
- formState
- isSubmitSuccessful
- フォーム内の情報の送信に成功した場合には、 true に更新されます。
- isDirty
- フォーム内のフィールドについて、どれか 1 つでも値が変更された場合には、 true になります。
- isSubmitted
- フォームで submit イベントが起きると、 true に更新されます。 reset メソッドが使われない限りは、 true の状態が維持されます。
- dirtyFields
- ユーザーによって値が変更されたフィールドをプロパティとするオブジェクトです。 React Hook Form がフィールド値と初期値を比較できるように、 useForm フックを経由して初期値が与えられることが重要になります。
- touchedFields
- ユーザーによって操作されたフィールドをプロパティとするオブジェクトです。
- isSubmitting
- フォーム内の情報が送信されている最中は、 true に更新されます。それ以外の場合は、 false でう。
- submitCount
- フォームで submit イベントが起きた回数を保持します。
- isValid
- フォーム内の全てのフィールドでバリデーションが成功した場合に、 true に更新されます。
- isValidating
- フォーム内のフィールドに対してバリデーションが実行されている場合には、 true に更新されます。それ以外は、 false です。
- isSubmitSuccessful
React Hook Form の useFormContext フックの詳細
useFormContext フックは、入れ子になっているコンポーネントに対して、必要になる props を簡単に渡せるようにするために用意されています。 React の useContext フックと同じような用途です。
useFormContext フックを使うには、あらかじめて入れ子のコンポーネント全体を FormProvider タグで囲んでおく必要があります。
React Hook Form の useWatch フックの詳細
useWatch フックは、コンポーネント単位の更新をおこないます。対象のコンポーネントに useForm フックの control を渡すことで、そのコンポーネントで useWatch フックの監視機能を使えるようになります。
React Hook Form の useFormState フックの詳細
useFormState フックは、それぞれのフォームの状態を取得できます。 useFormState フックは、他の useFormState フックや useForm フックに干渉しないので、意図しない再レンダリングを予防できます。
- control
- useForm フックによって取得できる control オブジェクトです。
- name
- 単一または複数のフィールド名です。
- disabled
- フォームの状態の監視を中止できるオプションです。
- exact
- フィールド名の状態を監視を完全一致にします。
- isDirty
- フォーム内のどれか 1 つでもフィールドの値に変更があると、 true に更新されます。
- dirtyFields
- ユーザーによって値が変更された全てのフィールド情報を持つオブジェクトです。フィールドの変更を検知する都合により、 useForm フックの defaultValues によって初期値が与えられている状態が好ましいです。
- touchedFields
- ユーザーによって操作された全てのフィールド情報を持つオブジェクトです。
- isSubmitted
- フォームの内容が submit イベントによって送信された時に、 true に更新されます。 reset メソッドが実行されるまでは、 true の状態が継続します。
- isSubmitSuccessful
- フォームにて submit イベントが起きた時に、 handleSubmit によって何かしらのエラーが検出されることなく、フォームの内容が正常に送信された場合に、 true に更新されます。
- isSubmitting
- フォームの内容が送信されている最中は true 、それ以外は false になります。
- submitCount
- フォームが送信された回数を保持しています。
- isValid
- フォームのフィールドに対して、バリデーションによるエラーがなければ、 true になります。
- isValidating
- フォームのフィールドにバリデーションを実行している最中は、 true になります。
- errors
- フォームのフィールドにバリデーションを実行した時のエラーを持つオブジェクトです。
ErrorMessage
関連する入力のエラーメッセージを表示するシンプルなコンポーネントです。
- name
- フィールドの名前です。
- errors
- React Hook Form によって作られたエラー情報を持つオブジェクトです。 FormProvider を使う場合には、オプションになります。
- as
- インライン形式のエラーメッセージです。
- render
- React の組み込み機能であるレンダープロップを利用できます。エラーメッセージを props に使いつつ、タグなどをカスタマイズした React 要素を表示させたい時に便利です。
React Hook Form の useFieldArray フックの詳細
useFieldArray フックは、制御されていないフィールドの配列として取り扱えます。また、配列に対して操作できる各種メソッドを取得できます。
useFieldArray フックを機能させるには、 useuseForm フックによって取得できる control オブジェクトを引数として設定する必要があります。
- name
- フィールドの登録名。要素は、オブジェクト形式にする。
- control
- useForm フックによって取得できる control オブジェクト。
- keyName
- フィールド配列の初期の key は「 id 」ですが、 key の名前を自由に変更できます。
- shouldUnregister
- アンマウント後に、フィールド配列の登録が削除されます。
フィールド配列を map メソッドに使ってタグを生成する場合は、不要な再レンダリングを減らすために、フィールドのタグに固有の key 属性値を設定することが推奨されています。
// divタグなどでフィールドタグを包む場合
{fields.map((field, index) => (
<div key={field.id}>
<input ... />
</div>
))}
// フィールドタグを じかに書く場合
{fields.map((field, index) => <input key={field.id} ... />)}
- fields
object & { id: string }
- すべてのフィールドの初期値と key をオブジェクト形式で持っています。それぞれのフィールドは非制御なので、 map メソッドを使ってタグとして出力する時には、一意の key 属性値を設定する必要があります。
- append
(obj: object | object[], { shouldFocus?: boolean; focusIndex?: number; focusName?: string; }) => void
- フィールド配列の最後の要素として、新たなフィールドを追加します。このメソッドによって、入力値が登録されます。
- prepend
(obj: object | object[], { shouldFocus?: boolean; focusIndex?: number; focusName?: string; }) => void
- フィールド配列の最初の要素として、新たなフィールドを追加します。このメソッドによって、入力値が登録されます。
- insert
(index: number, value: object | object[], { shouldFocus?: boolean; focusIndex?: number; focusName?: string; }) => void
- 第 1 引数のインデックスと第 2 引数の値(オブジェクト)を設定すると、フィールド配列のインデックスに対応する位置に、新たなフィールドを追加します。このメソッドによって、入力値が登録されます。
- swap
(from: number, to: number) => void
- 第 1 引数と第 2 引数にインデックスに設定すると、配列内のインデックスに対応する要素の位置を交換できます。
- move
(from: number, to: number) => void
- 第 1 引数 ( 移動元 ) と第 2 引数(移動先)のインデックスに設定すると、配列内の指定の位置に、要素を移動できます。
- update
(index?: number, obj: object) => void
- フィールドをオブジェクト形式で渡すと、配列内のフィールドを更新できます。
- replace
(obj: object[]) => void
- フィールドを要素に持つ配列を設定すると、現在の配列と置き換えます。
- remove
(index?: number | number[]) => void
- インデックスを設定すると、配列内の対応する位置のフィールドを削除します。インデックスを配列で設定すると、対応する位置のフィールドをまとめて削除できます。