react-hook-formハマりポイント② 🖍️registerが機能しない?ComponentPropsとrefについて
はじめに
react-hook-formを使っていて、ハマったポイントがいくつかあったのでまとめていきます。
※本記事では、reack-hook-formの説明は省きます。
その①
今回は、ComponentPropsを使用したコンポーネントへuseFormのregisterを渡す時のお話です。
ハマった点
前述の通り、ComponentPropsを使用して作成した入力コンポーネントに、HTML要素にregisterを渡すのと同様に記述したのですが、入力値が参照できず・・・🤔
-
ComponentPropsを使用してコンポーネントInputを作成
type InputProps = ComponentPropsWithRef<'input'>;
export const Input: FC<InputProps> = ({ ...props }, ref) => {
・・・
-
Inputにregisterを渡す
<Input
{...register('password')}
/>
ComponentPropsとは
HTML要素をカスタマイズしてコンポーネント化して使用することがよくあると思いますが、そのときに便利なのがComponentPropsです。
ComponentPropsを用いて型を定義することで、Reactの提供するElementが持つデフォルトのpropsを全て受け取れるようになります。
- 分割代入で全ての値を渡すことができる
-
{...props}の下に特定のpropsを記述すると独自の振る舞いになる。
import { ComponentPropsWithRef, FC } from 'react';
type InputProps = ComponentPropsWithRef<'input'>;
export const Input: FC<InputProps> = ({ ...props }, ref) => {
return (
<input
{...props}
className={'rounded border-2 px-4 py-2 text-sm' + props.className}
ref={ref}
/>
);
};
Refの許容を明示的に示す
refを許容したい場合はComponentPropsWithRefを使う必要があります。
許容したくない場合はComponentPropsWithoutRefを使用します。
そもそもRefとは
ref はstate と同様に、文字列、オブジェクト、さらには関数など、あらゆるものを指すことができます。
stateとは異なり、refは読み取り及び変更できるcurrentプロパティを持つ、プレーンなJavaScriptオブジェクトです。
解決方法
forwardRefにてrefを子コンポーネントに転送する
Reactでは親コンポーネントが子コンポーネントのrefに直接アクセスできないため、フォワーディングの必要があるようでした。
このforwardRefを使用して、先程のコンポーネントを修正してみます。
import { ComponentPropsWithRef, forwardRef, FC } from 'react';
type InputProps = ComponentPropsWithRef<'input'>;
export const Input: FC<InputProps> = forwardRef(({ ...props }, ref) => {
return (
<input
{...props}
className={'rounded border-2 px-4 py-2 text-sm' + props.className}
ref={ref}
/>
);
});
これで、無事にregister使用して値の参照ができるようになりました✨✨
さいごに
普段あまり意識せずrefを使っていましたが、react-hook-formをきっかけにコンポーネント間における作用について学びになりました。
少しでも、同様に詰まった方の助けになれば幸いです。
それでは、読んでいただきありがとうございました。
Discussion