React Hook Formのパフォーマンス
パフォーマンスはこのcustom hookを作成する主な目的の一つでした。 React Hook Formでは非制御コンポーネントによってregister関数をrefで実行しています。 このアプローチにより、ユーザーからの入力や値の変更により発生する再レンダリングの量を削減しています。 コンポーネントのページへのマウントも制御されていないことによりはるかに高速になります。こちらの他のライブラリとのマウントスピードの簡単な比較をご覧下さい。
アクセス可能な入力エラーとメッセージを作成するには?
React Hook Formは非制御コンポーネントに基づいているため、アクセス可能なカスタムフォームを簡単に構築できます。
import React from "react"; import { useForm } from "react-hook-form"; export default function App() { const { register, handleSubmit, formState: { errors } } = useForm(); const onSubmit = data => console.log(data); return ( <form onSubmit={handleSubmit(onSubmit)}> <label htmlFor="firstName">First name</label> <input id="firstName" aria-invalid={errors.firstName ? "true" : "false"} {...register('firstName', { required: true })} /> {errors.firstName && ( <span role="alert"> This field is required </span> )} <input type="submit" /> </form> ); }
クラスコンポーネントでも使えますか?
そのままでは動作しませんが、クラスコンポーネントを包むラッパーを作成して使用することは可能です。
クラスコンポーネント内でのHooksの使用は出来ませんが、クラスコンポーネントと Hooksを使用した関数コンポーネントを単一のDOM Tree内で混在させることは可能です。 クラスコンポーネントかHooksを使用した関数コンポーネントのどちらを利用するかは、 そのコンポーネントの実装の詳細に過ぎません。長い目で見れば、 HooksはReactのコンポーネントを書く際の最初の選択肢になっていくだろうと私達は予想しています。
フォームをリセットするには?
フォームをリセットする方法は2つあります。
- HTMLFormElement.reset()
フォームのリセットボタンのクリックと同等の効果を持つメソッドです。 フォーム内の
input/select/checkbox
要素の値のみリセットします。 - React Hook Form API:
reset()
React Hook Formの
reset
メソッドは、フォーム内の全てのフィールドの値をリセットし、フォーム内の全てのerrors
を消去します。
フォームの値を初期化するには?
React Hook Formは非制御コンポーネントによって出来ています。 非制御コンポーネントでは、それぞれのfieldに対してdefaultValue
かdefaultChecked
を指定出来ます。 実はこれよりも更に簡単な全てのインプット値の初期化方法をReact Hook Formは提供しています。 下記の例を参考して下さい。
import { useForm } from "react-hook-form"; export default function App() { const { register, handleSubmit } = useForm({ defaultValues: { firstName: "bill", lastName: "luo", email: "bluebill1049@hotmail.com" } }); const onSubmit = data => console.log(data); return ( <form onSubmit={handleSubmit(onSubmit)}> <input {...register("firstName")} /> <input {...register("lastName")} /> <input {...register("email")} /> <button type="submit">Submit</button> </form> ); }
refを共有するには?
React Hook Form では入力値を取得するためにref
が必要ですが、ref
を他の目的(ビューへのスクロールなど)に使用することもできます。下記の例を参考して下さい。
import React, { useRef } from "react"; import { useForm } from "react-hook-form"; export default function App() { const { register, handleSubmit } = useForm(); const firstNameRef = useRef(null); const onSubmit = data => console.log(data); const { ref, ...rest } = register('firstName'); return ( <form onSubmit={handleSubmit(onSubmit)}> <input {...rest} name="firstName" ref={(e) => { ref(e) firstNameRef.current = e // you can still assign to ref }} /> <button>Submit</button> </form> ); }
import React, { useRef } from "react"; import { useForm } from "react-hook-form"; type Inputs = { firstName: string, lastName: string, }; export default function App() { const { register, handleSubmit } = useForm<Inputs>(); const firstNameRef = useRef<HTMLInputElement | null>(null); const onSubmit = data => console.log(data); const { ref, ...rest } = register('firstName'); return ( <form onSubmit={handleSubmit(onSubmit)}> <input {...rest} name="firstName" ref={(e) => { ref(e) firstNameRef.current = e // you can still assign to ref }} /> <button>Submit</button> </form> ); }
refへのアクセスが出来ない場合は?
実はref
を使わずともregister
は使用出来ます。 加えてsetValue
とsetError
、trigger
の手動での使用も出来ます。
注: ただしref
が登録されていないため, React Hook Formはinputのイベントリスナーへの登録が出来ず、 そのため値やエラーの更新を手動で行わなければいけません
import React, { useEffect } from "react"; import { useForm } from "react-hook-form"; export default function App() { const { register, handleSubmit, setValue, setError } = useForm(); const onSubmit = data => console.log(data); useEffect(() => { register("firstName", { required: true }); register("lastName"); }, []); return ( <form onSubmit={handleSubmit(onSubmit)}> <input name="firstName" onChange={e => setValue("firstName", e.target.value)} /> <input name="lastName" onChange={e => { const value = e.target.value; if (value === "test") { setError("lastName", "notMatch") } else { setValue("lastName", e.target.value) } }} /> <button>Submit</button> </form> ); }
ブラウザのサポートは?
React Hook Formは全ての主要なブラウザに対応しています。
IE11をサポートしたい場合は、IE11バージョンのreact-hook-formをインポートして下さい。
import { useForm } from 'react-hook-form/dist/index.ie11'; // V6 import { useForm } from 'react-hook-form/dist/react-hook-form.ie11'; // V5' // Resolvers import { yupResolver } from '@hookform/resolvers/dist/ie11/yup';
最初のキーストロークが機能しない場合は?
defaultValue
の代わりにvalue
を使っていないかよく確認して下さい。
React Hook Formは非制御インプットを基にして作られているため、インプットの値をonChange
でstate
を通して変更する必要はありません。value
は使わずに、defaultValue
でのインプットの初期値 の設定のみ行って下さい。
MutationObserverが原因でテストに失敗した場合は?
テスト中にMutationObserver
が原因の問題が発生した場合は、mutationobserver
をインストールしテストのsetup.jsでインポートしてくださ い。
React Hook Form、FormikそれともRedux Form?
全てのライブラリはフォーム作成の体験を簡単で素晴らしいものにするという同じ問題を解決しようとしていますが 、3つのライブラリーの間にはいくつかの根本的な違いがあります。 react-hook-formは非制御入力を念頭に置いて開発されており、 ベストパフォーマンスのフォームを提供しようとし、再レンダリング数を出来る限り少なく抑えています。 さらに、react-hook-formはReact Hookによって構築され、hookとして使用されます。 つまり、コンポーネントをインポートしません。詳細な違いを以下に示します。
React Hook Form | Formik | Redux Form | |
---|---|---|---|
Component | uncontrolled | controlled | controlled |
Rendering | 最小限の再レンダリング | ローカル状態の変化に応じて再レンダリングします。つまり、入力時に変化します。 | 状態管理ライブラリ(Redux)の変更に応じて再レンダリングします。 これは、入力時に変化することを意味します。 |
API | Hooks | Component (RenderProps, Form, Field) + Hooks | Component (RenderProps, Form, Field) |
Package size | 小react-hook-form@3.26.2 | 中formik@2.0.1 | 大redux-form@8.2.6 |
Validation | Built-in & Yup | Build yourself or Yup | Build yourself or Plugins |
学習曲線 | 低い | 中 | 中 |
状況 | 小さなコミュニティ: 新しい成長中のライブラリ | 大きなコミュニティ: コミュニティによって十分に確立されたフォームライブラリ | 大きなコミュニティ: コミュニティによって十分に確立されたフォームライブラリ |
制御されたコンポーネントと組み合わせて使用することができますか?
短い回答: Yes
React Hook Form は、制御されたフォームを構築することを推奨していませんが、 制御されたコンポーネントと組み合わせて簡単に構築することができます。
それは、watch
API を使用して、各入力の変更を監視し、 value prop に割り当てるトリックです。
または、ラッパーコンポーネントの Controller を使用して、これらのカスタム登録を処理できます。
import { useForm, Controller } from "react-hook-form"; function App() { const { control } = useForm(); return ( <Controller render={({ field }) => <input {...field} />} name="firstName" control={control} defaultValue="" /> ); }
React Hook Form のテスト
act
の警告が表示されるのはなぜですか?React Hook Form の全てのバリデーションメソッドは非同期関数として扱われるため、act を
async
でラップすることが重要です。fireEvent で入力の変更がトリガーされないのはなぜですか?
React Hook Form は、入力の変更に
input
イベントを使用しています。 入力の変更がトリガーするために、 react-testing-library のfireEvent.input
に簡単に切り替えることができます。
あなたのサポートが必要です
React プロジェクトで React Hook Form が役立つと思う場合は、リポジトリとコントリビューターをサポートするためにスターを付けてください ❤