概要
Material UI(MUI)とReact Hook Formを使ったフォームを私なりに作ってみたので、備忘録として残します。
ログインフォームを題材としてフォームを作ります。
前提
- Reactがインストールされていること
- MUIとReact Hook Formがインストールされていること
npm i @mui/material @emotion/react @emotion/styled react-hook-form
サンプルコード(最小限)
React Hook Formが機能する必要最小限のコードです。
スタイルはつけておらず、これをもとにカスタマイズしていきます。
"use client"
import { Button, TextField } from "@mui/material"
import React from "react"
import { SubmitHandler, useForm } from "react-hook-form"
type Input = {
example: string
}
const page = () => {
const { register, handleSubmit } = useForm<Input>()
const onSubmit: SubmitHandler<Input> = (data) => console.log(data);
return (
<>
<form onSubmit={handleSubmit(onSubmit)}>
<TextField
id="outlined-basic"
label="Outlined"
{...register("example")}
/>
<div>
<Button type='submit' variant="contained">Contained</Button>
</div>
</form>
</>
)
}
export default page
完成したもの
"use client"
import { Box, Button, Container, Paper, TextField } from "@mui/material"
import React from "react"
import { SubmitHandler, useForm } from "react-hook-form"
type Input = {
email: string,
password: string
}
const page = () => {
const { register, handleSubmit } = useForm<Input>()
const onSubmit: SubmitHandler<Input> = (data) => console.log(data);
return (
<>
<Container sx={{ display: "flex", alignItems: "center", justifyContent: "center", height: "100vh" }}>
<Paper elevation={3} sx={{ width: "600px", padding: 4 }}>
<Box sx={{ textAlign: "center", fontSize: "24px", fontWeight: "bold" }}>ログイン</Box>
<form onSubmit={handleSubmit(onSubmit)}>
<TextField
fullWidth
id="outlined-basic"
label="Email"
type="email"
margin="normal"
{...register("email")}
/>
<TextField
fullWidth
id="outlined-basic"
label="password"
type="password"
margin="normal"
{...register("password")}
/>
<div>
<Button type='submit' variant="contained" sx={{ marginTop: "16px" }}>ログイン</Button>
</div>
</form>
</Paper>
</Container>
</>
)
}
export default page
私的にはシンプルなフォームが出来上がったかと思います。
ただ、入力されていなかった場合のエラー処理がまだ実装していません。
そこでReact Hook FormのuseFormにあるformStateを使っていきます。
また、MUIのTextFieldはエラー時のプロパティ(errorとhelperText)を用意しているようなのでこれと組み合わせて使っていきます。
"use client"
import { Box, Button, Container, Paper, TextField } from "@mui/material"
import React from "react"
import { SubmitHandler, useForm } from "react-hook-form"
type Input = {
email: string,
password: string
}
const page = () => {
const { register, handleSubmit, formState: { errors }} = useForm<Input>()
const onSubmit: SubmitHandler<Input> = (data) => console.log(data);
return (
<>
<Container sx={{ display: "flex", alignItems: "center", justifyContent: "center", height: "100vh" }}>
<Paper elevation={3} sx={{ width: "600px", padding: 4 }}>
<Box sx={{ textAlign: "center", fontSize: "24px", fontWeight: "bold" }}>ログイン</Box>
<form onSubmit={handleSubmit(onSubmit)}>
<TextField
fullWidth
id="outlined-basic"
label="Email"
type="email"
margin="normal"
{...register("email", { required: true })}
error={errors.email ? true : false }
helperText={errors.email ? "Email is required" : ""}
/>
<TextField
fullWidth
id="outlined-basic"
label="Password"
type="password"
margin="normal"
{...register("password", { required: true })}
error={errors.password ? true : false }
helperText={errors.password ? "Password is required" : ""}
/>
<div>
<Button type='submit' variant="contained" sx={{ marginTop: "16px" }}>ログイン</Button>
</div>
</form>
</Paper>
</Container>
</>
)
}
export default page
ログインボタンが押されて入力欄が空だったときはエラーが表示されるようになりました。
まとめ
MUIとreact-hook-formを使って簡単なフォームを作ってみました。
理解の助けになっていただければ幸いです。
ただ、調べているうちにMUIとreact-hook-formを複合したライブラリがあるようで、これを試してみたいと思います。
参考・引用