Closed6

React Hook Form 初心者の気づきメモ

T.KawashimaT.Kawashima

DOMを参照したいときはregisterの後ろにrefを書け

'ref' is specified more than once, so this usage will be overwritten.

useRef<input />のDOMを参照しようとすると、React Hook Formの参照と競合してエラーが出る。

上書きするためには、refregisterより後ろに書く

Input.tsx
import { type FC, useRef } from 'react';

const Input: FC<{name: string, placeholder: string}> = ({ name, placeholder }) => {
  const { register } = useFormContext();
  const inputRef = useRef<HTMLInputElement>(null);

  return (
    <input
      placeholder={placeholder}
      {...register(name, { required: true })}
      ref={inputRef} // refを上書き
    />
  );
};

export default Input;

⚠️refを上書きしたときの注意点⚠️
useFormContextを使っていると、参照がうまくいかずにisValidが正常に動かなくなる。

From.tsx
import { type FC } from 'react';
import { useForm, FormProvider } from 'react-hook-form';

import Input from '@/components/Input';

const Form: FC<{name: string}> = ({ name }) => {
  const { register } = useFormContext();

  const onSubmit = () => console.log('送信');

  return (
    <FormProvider {...methods}>
      <form onSubmit={methods.handleSubmit(onSubmit)}>
        <Input name="age" placeholder="年齢" />
        <button disabled={!methods.formState.isValid}>送信</button> // Inputに入力しても活性にならない
      </form>
    </FormProvider>
  );
};

export default Form;
T.KawashimaT.Kawashima

二重送信防止にはisSubmittingを使え

簡単に二重送信防止できる

onSubmitの処理には、ちゃんとasync/awaitで終わるまで待つような処理を入れる

Input.tsx
import { type FC } from 'react';

const Input: FC<{name: string, placeholder: string}> = ({ name, placeholder }) => {
  const methods = useForm();

  return (
    <input
      placeholder={placeholder}
      {...register(name, { required: true })}
      disabled={!methods.formState.isValid || methods.formState.isSubmitting}
    />
  );
};

export default Input;

参考:useForm - setValue - React Hook Form

T.KawashimaT.Kawashima

初期値からの変更を検知する場合はisDirtyを使え

フォームの初期値(defaultValues)から変更があった場合のみ送信できるようにしたい場合は、disable!isDirtyを使う

Input.tsx
const Input: FC = () => {
  const { formState: { isDirty }} = useForm({defaultValues: {prefecture: '東京都'}});

  return (
    <input {...register("prefecture")} />
    <button type="submit" disabled={!isDirty}>
  );
};

参考:useFormState - React Hook Form

このスクラップは2024/01/25にクローズされました