LoginSignup
0
2

More than 1 year has passed since last update.

React Hook Form + Material UI + yup + TypeScript で良い感じのフォームを作成する

Posted at

はじめに

React Hook Form、Material UI、yup を組み合わせたフォームを作成する方法をメモしておきます。

始め方シリーズ

良い感じの環境構築についても記事を書いているので、よければこちらもご覧ください。

バージョン

package.json
{
  "dependencies": {
    "@hookform/resolvers": "^2.8.3",
    "@mui/material": "^5.1.1",
    "react-hook-form": "^7.20.2",
    "yup": "^0.32.11"
  },
}

コード

Form.tsx
import { yupResolver } from "@hookform/resolvers/yup/dist/yup";
import { Button, Checkbox, TextField } from "@mui/material";
import { Controller, useForm } from "react-hook-form";
import * as yup from "yup";

interface FormValues {
  hoge: string;
  num: number;
  checked: boolean;
}

const schema: yup.SchemaOf<FormValues> = yup.object({
  hoge: yup.string().required("必須だよ"),
  num: yup.number().required("必須だよ").min(20, "20以上にしてください"),
  checked: yup.boolean().required("必須だよ").isTrue("チェックしてください"),
});

const Form = (): JSX.Element => {
  const {
    handleSubmit,
    formState: { errors },
    control,
  } = useForm<FormValues>({
    defaultValues: {
      hoge: "",
      num: 1,
      checked: true,
    },
    resolver: yupResolver(schema),
  });

  return (
    <form onSubmit={handleSubmit((data) => console.log(data))}>
      <Controller
        name="hoge"
        control={control}
        render={({ field }): JSX.Element => (
          <TextField
            {...field}
            type="text"
            label="hoge のラベル"
            multiline
            rows={8}
            variant="filled"
            fullWidth
            error={"hoge" in errors}
            helperText={errors.hoge?.message}
          />
        )}
      />

      <Controller
        name="num"
        control={control}
        render={({ field }): JSX.Element => (
          <TextField
            {...field}
            type="number"
            label="num のラベル"
            variant="filled"
            fullWidth
            error={"num" in errors}
            helperText={errors.num?.message}
          />
        )}
      />

      <Controller
        name="checked"
        control={control}
        render={({ field }): JSX.Element => (
          <Checkbox onChange={(e): void => field.onChange(e.target.checked)} checked={field.value} />
        )}
      />

      <Button type="submit" variant="contained">
        submit
      </Button>
    </form>
  );
};

export default Form;

参考にさせていただいたサイト

  • 公式ドキュメント

  • こちらは register を使う方法
  • 公式が Contoller を使用していたので、そちらに合わせました。

  • yup の import でエラーが出たので、この回答の対応をしました。
0
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
2