React-Hook-Form 学びメモ
Controlled Component とUncontrolled Component
以下の認識。
- Controlled Componentはformの値をstateで管理。
- Uncontrolled Componentsはformの値をDOMで管理。
ただ、ReactはControlldedを推奨していて、これはReactが生まれた歴史から考えても当然のように思える。
自分が使うとしても基本的にControlled Componentを利用する。
ref属性が必要な時
React Hook FormでいうとsetFocusなどを使いときなど。
refとは、DOMにアクセスするための機能?
意外とこの辺りについては調べても詳細が中々出てこなかったが、DOMを参照したいときに使うとのこと。
DOM側のみで管理されている情報を参照したいときに使うものだとイメージしている。
Componentでfocusの管理をしたいときなどに、どうしてもrefが必要
RHFのController経由で取得できるrefを使ったフォーカスのデモを作ってみました
以下の部分がFocusする実装になります
この実装があると、アイテム追加するたびに、入力フィールドへフォーカスが自動であたるようになります
また、Submit時にバリデーションエラーがあると、バリデーションエラーが起きている先頭の入力フィールドへフォーカスがあたるようになります
<Input
{...omit(field, ["ref"])}
/**
* @see https://codesandbox.io/p/sandbox/react-hook-form-with-mui-one-time-password-input-forked-eb61t2?file=%2Fsrc%2Findex.js%3A30%2C13-35%2C17
*
* @see https://github.com/orgs/react-hook-form/discussions/10167#discussioncomment-5430386
*/
ref={(elem: HTMLInputElement) => {
field.ref({
...elem,
focus: () => elem.querySelector("input")?.focus(),
});
}}
type="text"
placeholder="劇場版SHIROBAKO"
sx={(theme) => ({
"--variant-borderWidth": "2px",
...(errorInfo != null && {
"--variant-borderWidth": "2px",
"--variant-outlinedBorder": theme.palette.danger[500],
"&.MuiInput-root:before": {
"--Input-focusedHighlight": theme.palette.danger[500],
},
}),
})}
/>;
useFormContext
この辺りについて調べる。
- useFormContextにはuseFormのようにFormの型を渡せるが、これは具体的にどんなメリットがあるのか。
- Pathについて
Controllerを利用する場合のcontrol Propsを利用するメリットについて
正直これがよくわからない。
useFormのcontrolは↓こんな説明が。
This object contains methods for registering components into React Hook Form.
Controllerを利用するということは、ラッピングするfieldはControlled Componentになる認識。
controlを利用するメリット、利用することで変化することは?
公式でもControllerのcontrolにuserFormのcontrolを渡しているのはなぜか不明。
MUIとかを使ってるときに必要になるのかな・・?
FormProviderを使っていたからオプショナルになっていて、メリットを感じられなかったが、FormProviderを利用しない場合は利用しないとエラーになる。
ソース見れてないけどformのcontextがあって、それにfieldを登録・アクセス・するために必要ってことなのかな。
ControllerのdefaultValue
useFormのdefaultValuesとControllerのdefaultValueどちらも設定している場合、useFormで設定したdefaultValueが優先される。
基本的にはuseFormでdefaultValueを設定してあげた方が、子コンポーネント側にとっても良いことな気がする。
子コンポーネント内でuseWatchやgetValueを利用する際、レンダリングのタイミングを特に気にしなくて済む。子コンポーネント内で、自身が持つfieldのvalueを取得した時とかもその方が余計なことをしなくて済む。
ネストされたComponent内でfieldのvalueを取得したいとき
子コンポーネント内で自身がもつfieldのvalueを取得し、その結果から出力を分岐させたい時もあると思う。
その場合は、useWatchでdefaultValueを渡してあげるとかの選択になるのか?
useFormで設定したdefaultValuesなら、問題なく子コンポーネント内でも取得できる。
やっぱりRHFでformにデフォルトで値を入れたいときは、useFormのdefaultValuesで設定してあげるのが一番良い気がする。