とーますメモ

Ruby on Rails / Goなどの学習メモ

React Hook Form v7 × Material UIを使用したときのメモ書き

React Hook Formを使用するのは初めて。
React Hook Formを使用することでform内の値を管理するstateが不要になり、バリデーション機能も含まれているため、コード量を大幅に減らすことができる。またネット上にサンプルも非常に多いのも魅力的。

form値の監視や、他のUIライブラリとも組み合わせるのも可能。

React Hook Form ファーストインプレッション

v7について

React Hook Formはv7では書き方が以前のバージョンとは違っている。
ちなみに公式の説明はこちら
Migrate From V6 to V7 | React Hook Form - Simple React forms validation

register関数の使い方
- <input ref={register({ required: true })} name="test" />
+ <input {...register('test', { required: true })} />

スプレッド構文を使用することでシンプルに記述できるようになった。
以下が影響が大きそうな部分。

Controller
- <Controller as={<input />} />
+ <Controller render={({ field }) => <input {...field} />}

- <Controller render={(props, meta) => <input {...props} />} />
+ <Controller render={({ field, fieldState }) => <input {...field} />} />

as属性は廃止になり、代わりにrender属性をv7からは使用する。
render属性はfieldとfieldStateを含むオブジェクトを返す。

errros
- const { errors } = useForm();
+ const { formState: { errors } } = useForm();

errorsオブジェクトはfromStateオブジェクト内に属することになった。

実装時に困ったこと

Select要素のラベル表示にすごく困った。
React Hook FormとMaterial UIを併せたSelectのサンプルを紹介しているサイトは結構あるけど、v7のやり方でやってる例が意外となく、Material UIのform独特なかっこいいラベルのUIが、うまく動作しないという問題が発生した。

結論から言うと、以下のサイトさんを参考にし
React 初心者が Material-UI で今どきの Web フォームを作ってみた(react-hook-form編) | DevelopersIO

Controller内にTextFieldを入れて、Textfieldにselect属性をつけることで
Material UIのあのかっこいいUI効果があるラベルが実装できた。

<Controller
  name="sample_select"
  control={control}
  defaultValue={"default value"}
  render={({ field }): JSX.Element => (
    <TextField {...field} fullWidth size="small" select label={"Sample Select"}>
      {options.map((v) => (
        <MenuItem key={v.name} value={v.id}>
          {v.name}
        </MenuItem>
      ))}
    </TextField>
  )}
/>


[参考]
Using Material UI with React Hook Form - LogRocket Blog