nomurabbitのブログ

nomurabbitのブログはITを中心にした技術ブログです。

nomurabbitのブログ

【React】React Hook Formの "はじめる" を始めてみた Part5【Typescript】

この記事はReact Hook Formの公式サイトにあるはじめるの項目を元に構成されています。ReactとTypescriptのサンプルコードを使って解説しています。

こんにちは!らびです。今回はReact Hook Formに関する記事です。

公式サイトのチュートリアルを使って一緒に勉強していきましょう。

UI ライブラリを使用する

今回はいよいよUI ライブラリを使用します。サンプルコードではmuiを使用しています。それでは、サンプルコードをReactのプロジェクトにうつしてみましょう。

import React from 'react';
import Select from "react-select";
import { useForm, Controller, SubmitHandler } from "react-hook-form";
import {List, ListItem, Input} from '@mui/material';
import ResponsiveDrawer from '../components/layout/ResponsiveDrawer';

interface IFormInput {
    firstName: string;
    lastName: string;
    iceCreamType: {label: string; value: string };
  }

const Home5 = () => {
    const { control, handleSubmit } = useForm<IFormInput>();
    const onSubmit: SubmitHandler<IFormInput> = (data) => {
      console.log(data)
    };
  
  return (
    <ResponsiveDrawer>
      <div>
        <form onSubmit={handleSubmit(onSubmit)}>
          <List>
            <ListItem>
              <label>First Name</label>
              <Controller
                name="firstName"
                control={control}
                defaultValue=""
                render={({ field }) => <Input {...field} />}
              />
            </ListItem><ListItem>
              <label>Age</label>
              <Controller
                name="iceCreamType"
                control={control}
                render={({ field }) => <Select 
                  {...field} 
                  options={[
                    { value: "chocolate", label: "Chocolate" },
                    { value: "strawberry", label: "Strawberry" },
                    { value: "vanilla", label: "Vanilla" }
                  ]} 
                />}
              />
            </ListItem><ListItem>
              <input type="submit" />
            </ListItem>
          </List>
        </form>
      </div>
    </ResponsiveDrawer>
  );
}
  
export default Home5;

実行結果はこんな感じだジョ。

f:id:nomurabbit:20220112232706p:plain

import

importですが、今回はuseFormSubmitHandlerの他にControllerをインポートしています。

import { useForm, Controller, SubmitHandler } from "react-hook-form";

その先のプログラムを見ると、renderに渡された無名関数muiのコンポーネントが指定されているのがわかりますね。

import {List, ListItem, Input} from '@mui/material';

…省略
<Controller
  name="firstName"
  control={control}
  defaultValue=""
  render={({ field }) => <Input {...field} />}
/>

Controller

サンプルコード中にControllerタグが2か所出てきます。いずれもrenderに、({ field }) => {muiのコンポーネント}といった無名関数が渡されています。

…省略
<Controller
  name="firstName"
  control={control}
  defaultValue=""
  render={({ field }) => <Input {...field} />}
/>
…省略
<Controller
  name="iceCreamType"
  control={control}
  render={({ field }) => <Select 
    {...field} 
    options={[
      { value: "chocolate", label: "Chocolate" },
      { value: "strawberry", label: "Strawberry" },
      { value: "vanilla", label: "Vanilla" }
    ]} 
  />}
/>

無名関数に渡されるfieldって何だジョ?

Controllerの定義を見てみると、ControllerProps型プロパティだということがわかります。

export declare type ControllerProps<TFieldValues extends FieldValues = FieldValues, TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>> = {
    render: ({ field, fieldState, formState, }: {
        field: ControllerRenderProps<TFieldValues, TName>;
        fieldState: ControllerFieldState;
        formState: UseFormStateReturn<TFieldValues>;
    }) => React.ReactElement;
} & UseControllerProps<TFieldValues, TName>;


さらに定義をたどっていくと、fieldにはonChange、onBlur、value、name、refといったパラメータが定義されていることがわかります。

export declare type ControllerRenderProps<TFieldValues extends FieldValues = FieldValues, TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>> = {
    onChange: (...event: any[]) => void;
    onBlur: Noop;
    value: UnpackNestedValue<FieldPathValue<TFieldValues, TName>>;
    name: TName;
    ref: RefCallBack;
};

このパラメータたちmuiのコンポーネントに渡していたんですね。

まとめ

というわけで、今回もReact Hook Formはじめるについて勉強してきましたが、いかがでしたでしょうか?

UIライブラリReact Hook Formを使う場合はControllerの引数にUIライブラリのコンポーネントを渡すのがポイントですね!

次回もぜひご覧ください。では!

参考

React Hook Form
react-hook-form.com