리액트 훅 폼은 Yup, Zod, Superstruct & Joi를 통해 스키마 기반 폼 유효성 검사를 지원한다. 이를 통해 스키마에 대한 입력 데이터를 유효하게 처리하고 오류 또는 유효한 결과를 반환한다.
<출처 - react-hook-form 공식문서 번역>
런타임 값 구문 분석 및 유효성 검사를 위한 스키마 빌드. 스키마를 정의하거나, 일치하도록 값을 변환하거나, 기존 값의 shape을 주장하거나, 둘 다 지정합니다. 스키마는 표현력이 뛰어나며 복잡한 상호 의존적인 유효성 검사 또는 값 변환을 모델링할 수 있다.
<출처 - yup 깃허브 번역>
npm install @hookform/resolvers yup react-hook-form
import * as yup from "yup"
const firstName = yup
.string()
.required()
// firstName은 string이어야 하며 필수 조건이다.
const age = yup
.number()
.positive()
.integer()
.required()
// age는 number 타입이어야 하며, 양수, 정수, 필수 조건이다.
import * as yup from "yup"
const schema = yup
.object({
firstName: yup.string().required(),
age: yup.number().positive().integer().required(),
})
.required() //
// yup.object를 선언하여 키(검사할 속성): 값(유효성 로직)을 schema에 담아준다.
import * as yup from "yup"
const schema = yup.object().shape({
firstName: yup
.string()
.required,
age: yup
.number()
.positive()
.integer()
.required()
})
주로 정규 표현식으로 복잡한 유효성 검사가 필요할 때 matches() 안에 해당 로직을 넣어준다.
email: yup
.string()
.required("이메일을 필수로 입력해주세요")
.matches(
/^[0-9a-zA-Z]([-_.]?[0-9a-zA-Z])*@[0-9a-zA-Z]([-_.]?[0-9a-zA-Z])*\.[a-zA-Z]{2,3}$/i,
"email 형식에 맞지 않습니다"
),
// consts/regex.js
export const REGEX = {
email: /^[0-9a-zA-Z]([-_.]?[0-9a-zA-Z])*@[0-9a-zA-Z]([-_.]?[0-9a-zA-Z])*\.[a-zA-Z]{2,3}$/i,
password: //생략,
phone: // 생략,
age:
}
// consts/schema.js
import { REGEX } from "./regex";
email: yup
.string()
.required("이메일을 필수로 입력해주세요")
.matches(REGEX.email),
나는 먼저 재사용 가능한 <input />
태그를 Controller로 만들어주었다.
import { FormHelperText, TextField } from "@mui/material";
import { Controller } from "react-hook-form";
const OneInput = ({ control, name, label, value, errors, ...rest }) => {
return (
<Controller
control={control}
name={name}
render={({ field: { onChange, value } }) => (
<div style={{ marginBottom: "20px" }}>
<TextField
style={{ width: "400px" }}
label={label}
variant="standard"
value={value}
onChange={onChange}
error={errors[name]} // mui ui error 밑줄 빨갛게
/>
{errors[name] && (
<FormHelperText style={{ textAlign: "center" }} error>
{errors[name].message}
</FormHelperText>
)}
</div>
)}
/>
);
};
export default OneInput;
react-hook-form에서 Controller를 import하여 control
, name
, render
props를 넘겨준다.
mui 라이브러리에 Controller와 연결할 수 있는 에러메세지 컴포넌트가 있어 사용해보았다.
// Form.js
import { useForm } from "react-hook-form";
import { yupResolver } from "@hookform/resolvers/yup";
import OneInput from "./one-input";
import { schema } from "consts/schema";
import { Button } from "@mui/material";
const SignUpForm = () => {
const {
handleSubmit,
formState: { errors },
control,
} = useForm({
resolver: yupResolver(schema),
});
/*
1. yupResolver: yup 라이브러리의 스키마 유효성 검사를 react-hook-form과 통합
*/
const onSubmit = (data) => {
console.log("onSubmit", data);
};
return (
<form onSubmit={handleSubmit(onSubmit)}>
<h2>회원가입</h2>
<OneInput control={control} name="email" label="Email" errors={errors} />
<OneInput
control={control}
name="password"
label="Password"
errors={errors}
/>
<OneInput
control={control}
name="passwordConfirm"
label="Password Confirm"
errors={errors}
/>
<OneInput control={control} name="phone" label="phone" errors={errors} />
<OneInput control={control} name="age" label="Age" errors={errors} />
<Button variant="outlined" type="submit">회원가입</Button>
</form>
);
};
export default SignUpForm;
기존 리액트 훅 폼은 useForm() 이었다면
yup에서는 yupResolver를 import하여 유효성 검사 로직을 작성한 schema를 import하여 매개 변수로 넣어주면 검사 준비 끝!
useForm({ resolver: yupResolver(schema) }