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