はじめに
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;
参考にさせていただいたサイト
- 公式ドキュメント
- 公式の examples
- 中でも Controller (MUI, React-Select and etc)が参考になります
- こちらは
register
を使う方法 - 公式が
Contoller
を使用していたので、そちらに合わせました。
- yup の import でエラーが出たので、この回答の対応をしました。