Skip to content

Latest commit

 

History

History
130 lines (103 loc) · 3.27 KB

fde54cc14aa02d.md

File metadata and controls

130 lines (103 loc) · 3.27 KB
title emoji type topics published
【ReactHookForm✖️zod】 FormProviderで簡単フォーム実装
💭
tech
React
TypeScript
Javascript
true

ReactHookForm の FormProvider と zod を用いてバリデーションやエラーメッセージの管理など実装していきます。

使用するライブラリ

https://www.npmjs.com/package/zod https://www.npmjs.com/package/react-hook-form https://www.npmjs.com/package/@hookform/resolvers

FormProvider の実装

FormProvider を使うことで複数のフォームの状態やメソッドを管理しやすくなります。 zodResolver で後述する zodSchema の適応を行い、バリデーションやエラーメッセージの設定を可能にします。

import { useForm, FormProvider } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";

function App() {
  const methods = useForm({
    //zodResolverでスキーマを指定
    resolver: zodResolver(sampleFormSchema),
  });
  const { handleSubmit } = methods;
  return (
    <FormProvider {...methods}>
      <form onSubmit={handleSubmit((data) => console.log(data))}>
        <InputField name='input' />
        <SelectField name='select' />
        <button type='submit'>Submit</button>
      </form>
    </FormProvider>
  );
}

スキーマの作成

ここで zod を使用してバリデーションやエラーメッセージを設定していきます。

import { z } from "zod";

const sampleFormSchema = z.object({
  input: z.string().nonempty({
    message: "inputは必須です",
  }),
  select: z.string().nonempty({
    message: "selectは必須です",
  }),
});

各フィールドコンポーネントの作成

React Hook Form の useFormContext を使用すると、メソッドを呼び出したりフォーム全体で状態を共有できるようになります。 今回は register メソッドを使って props で受け取った key で form に値を渡していきます。

formState を利用して先程設定した message を取り出して error として表示させます。

Select

import { useFormContext } from "react-hook-form";

type Props = {
  name: string;
};
function SelectField(props: Props) {
  const methods = useFormContext();
  return (
    <>
      <select {...methods.register(props.name)}>
        {["", "one", "two", "three"].map((value) => (
          <option key={value} value={value}>
            {value}
          </option>
        ))}
      </select>

      {methods.formState.errors[props.name] && (
        <p>{methods.formState.errors[props.name]?.message as string}</p>
      )}
    </>
  );
}

Input

import { useFormContext } from "react-hook-form";

type Props = {
  name: string;
};
function InputField(props: Props) {
  const methods = useFormContext();
  return (
    <div>
      <input {...methods.register(props.name)} />
      {methods.formState.errors[props.name] && (
        <p>{methods.formState.errors[props.name]?.message as string}</p>
      )}
    </div>
  );
}

サンプルリポジトリ

https://github.com/taku10101/reacthookform-example

参考文献

https://react-hook-form.com/docs/formprovider

https://react-hook-form.com/docs/useformcontext

https://react-hook-form.com/docs/useformstate#useFormRef