はじめに
初見時に公式を読んで「どういうこと?」となったためまとめます。公式読んでスッキリしていない方はこちらを読んでからならスムーズに読めるかもしれません。
また、この記事はpartに分けています。part1ではRHFだけのバリデーション。part2ではyupとの併用。part3ではMUIのバリデーションを行います。
パッケージインストール
npm install react-hook-form
yarn add react-hook-form
RHF基本的な使い方
詳細な使い方を説明する前にinput要素の値の取得からバリデーションという一連の流れを説明します。
まずはじめにinput要素にRHFのregisterという関数を適用することで、input要素をRHFから参照できるようにします。次に適用するバリデーションをregister関数に登録します。最後にsubmitボタンを作成しonSubmitで発火する関数をRHFから取得します。
では次の項目から上記で説明した内容とエラーメッセージの出し方の詳細な方法を説明します。
目次
- フィールドの登録
- バリデーション適用
- Submitする
- エラーメッセージの出し方
フィールドの登録
以下React-Hook-Form(RHF)公式のクイックスタートより引用
React Hook Form の重要なコンセプトの一つは、非制御コンポーネント ([Uncontrolled Components]を
フックに登録(register
) し、フォームフィールドの値を検証と収集できるようにすることです。
URL: https://react-hook-form.com/jp/get-started#Quickstart
これだけではよくわからないので補足します。
RHFは使えばinput要素の値(value属性)をuseStateで監視する必要はありません。RHFは非制御コンポーネントの入力を監視してバリデーションすることができます。
バリデーションするにはRHFが提供するカスタムフックである、registerを使って非制御コンポーネントを登録する必要があります。registerはカスタムフックなので以下の方法で取得できます。
const { register } = useForm();
そして実際の非制御コンポーネントの登録は以下のように行います。
<input {...register("email")} />
これで上記のinput要素は"email"というname属性で登録されました。
これで、フォームフィールドのバリデーションと収集ができるようになりました。
※name属性は必ず一意になるようにする必要があります。
バリデーション
registerによる登録はできたので、次はバリデーションを適用します。
yupなどのバリデーションライブラリを利用する方法がありますが、今回はRHFで用意されているものを使ってバリデーションしていきます。
やり方は簡単でregisterの第2引数にバリデーションを定義したオブジェクトを渡すだけです。
<input {...register("email", { required: true, maxLength: 20 } )} />
上記は「必須入力」・「最大文字数20文字」というバリデーションを行っています。
他にもあるので公式を見て自分が実装したバリデーションを探してみてください。
https://react-hook-form.com/api/useform/register
Submitする
次にSubmitしたいと思います。コードは以下の様になっているとします。
import { useForm } from "react-hook-form";
// コンポーネント
export const App = () => {
// カスタムフック
const { register } = useForm();
// jsx
return (
<input {...register("email", { required: true, maxLength: 20 } )} />
);
};
まずは、formのHTML要素とsubmitするためのボタンを追加します。
<form>
<input {...register("email", { required: true, maxLength: 20 } )} />
<input type="submit" />
</form>
これで、submitする準備はできました。あとはonSubmitをform要素に持たせればよいです。
ここでuseFormからhandleSubmit関数を取得してonSubmitのイベントリスナーに登録します。
const { register, handleSubmit } = useForm();
<form onSubmit={handleSubmit()}>
<input {...register("email", { required: true, maxLength: 20 } )} />
<input type="submit" />
</form>
handleSubmitの引数には関数(formSubmitHandler)を渡します。formSubmitHandler
はinputの値をオブジェクトで受け取ることが出来ます。
またformSubmitHandlerの定義と同時に「formSubmitHandler」と「inputの値」の型定義をしてあげましょう。
- formSubmitHandlerの型定義はrect-hook-formからimportできます。
- inputの値はオブジェクトで渡ってくるのでオブジェクトで定義します。
- useFormにもinputの値の型定義を渡します。
// 渡す関数の型定義はimportする
import { useForm, SubmitHandler } from "react-hook-form";
// inputの値の型定義
type IFormInputs = {
email: String;
};
// SubmitHandlerにはinputの値の型定義を渡します。
const formSubmitHandler: SubmitHandler<IFormInputs> = (data) => {
console.log(data);
};
// コンポーネント
export const App = () => {
// useFormにも型定義をします
const { register, handleSubmit } = useForm<IFormInputs>();
// jsx
return (
<form onSubmit={handleSubmit(formSubmitHandler)}>
<input {...register("email", { required: true, maxLength: 20 } )} />
<input type="submit" />
</form>
);
};
コメントなしのコード
import { useForm, SubmitHandler } from "react-hook-form";
type IFormInputs = {
email: String;
};
const formSubmitHandler: SubmitHandler<IFormInputs> = (data) => {
console.log(data);
};
export const App = () => {
const { register, handleSubmit } = useForm<IFormInputs>();
return (
<form onSubmit={handleSubmit(formSubmitHandler)}>
<input {...register("email", { required: true, maxLength: 20 } )} />
<input type="submit" />
</form>
);
};
これで完成です。20文字以下の入力があればsubmitした瞬間にformSubmitHandlerが動いて
console.logに以下の様な内容が出力されるはずです。
{email: "入力値"}
エラーメッセージの出し方
エラーメッセージを出すのは簡単です。
useFormからerrorオブジェクトを取得し、そのエラーオブジェクトの中身がある場合はエラーメッセージを出すようにします。
エラーオブジェクはregisterで登録したname属性のプロパティを持ちます。submitの時にバリデーションをパスできなければerrorオブジェクトの中身が生成されます。
import { useForm, SubmitHandler } from "react-hook-form";
type IFormInputs = {
email: String;
};
const formSubmitHandler: SubmitHandler<IFormInputs> = (data) => {
console.log(data);
};
export const App = () => {
const {
register,
handleSubmit,
formState: { errors } // errorオブジェクト
} = useForm<IFormInputs>();
return (
<form onSubmit={handleSubmit(formSubmitHandler)}>
<input {...register("email", { required: true, maxLength: 20 })} />
<input type="submit" />
<br />
// errorオブジェクトのemailが値を持つとき
{errors.email && <span style={{ color: "red" }}>エラー</span>}
</form>
);
};
最後に
以上でRFHだけを使ったバリデーションの説明は終わりです。より詳細なバリデーション方法を知りたい場合は公式を読むと良いでしょう。また、ここで紹介しなかったwatchなどのuseFormが持つAPIを確認することも重要なことかもしれません。(watchは使い道がわからなかったので、紹介できませんでした。)
part2ではyupを使ったバリデーションを説明します。part3ではMUIをバリデーションしたいと思います。
以上です。記事を読んでくださりありがとうございました。