React Hook Formの基本まとめ その4(formProviderで親子間でフォーム情報をやりとりする)

こんにちは! 今回はReact Hook Formの基本まとめの4回目(最終回)です。

formProvider

コンポーネント

import { useForm, FormProvider } from 'react-hook-form'
import ChildComponent from '/ChildComponent';

const ParentForm = () => {
  const methods = useForm()
 
  const onSubmit = (data) => {
    console.log(data)
  }

  return (
    <FormProvider {...methods}>
       <form onSubmit={methods.handleSubmit(onSubmit)}>
         <ChildComponent />
          <button type="submit">送信</button>
       </form>
    </FormProvider>
  )
}

解説

FormProvider

  • FormProviderで囲われたChildrenは、useFormContextを使うことでFormProviderが提供する値にアクセスできる
  • FormProviderは <FormProvider { ...methods } >のように、提供する値を指定できる
  • この例では、methodsはuseFormが返す値を全て保持しており、スプレッド構文ですべてを提供している

methods

  • useFormでmethodsという変数(名前はなんでもよい)に戻り値を格納しているのは、FormProviderでまとめてすべての値を渡すときに都合が良いため
  • これまでは、 const { control, handleSubmit } = useForm()のように、戻り値の中から指定して分割代入していたが、Providerにまとめて渡すのに都合が良いので、分割代入せずに受け取っている

methods.handleSubmit

  • これまではhandleSubmitはuseFormから分割代入していたので、handleSubmitと使えていたが、今回は分割代入していないので、methods.handleSubmitと指定する必要がある

コンポーネント

import { useFormContext, Controller } from 'react-hook-form'
import { TextField } from '@mui/material'

const ChildComponent = () => {
  const { control } = useFormContext();

  return (
    <Controller
      name="name"
      control={control}
      render={({ field, fieldState }) => (
        <TextField
           {...field}
           error={!!fieldState.error}
           helperText={fieldState.error?.message}
         />
      )}
     />
    <Controller
       name="age"
       control={control}
       render={({ field, fieldState }) => (
         <TextField
            {...field}
            type="number"
            error={!!fieldState.error}
            helperText={fieldState.error?.message}
          />
       )}
     />
  )
}

解説

useFormContext

  • 親にFormProviderが存在する場合に使用可能
  • 親のFormProviderが渡しているデータを取得可能
  • 今回は const { control } = useFormContext();としているので、controlを受け取っている
  • この control を使うことで、親のRHFにフォームの入力値を渡したり状態の管理をさせることができる

useWatch

  • サンプルコードでは使っていないが、フォームの値をリアルタイムに取得できるメソッド
const name = useWatch({ control, name: "name" })
  • 監視対象のcontrolと、取得したいフォームの名前を指定する

おわりに

これでReact Hook Formの基本まとめはひとまず終了です。順を追って見ていったおかげで、何とかコンポーネントをまたぐProviderの使い方までたどり着くことができました。ちなみに、学習方法はChatGPTに色々質問したことをベースにまとめているので、もしかすると古い情報や誤りがあるかもしれません。気づいたことがあれば適宜直していこうと思います。