# 지원하는 리액트 버전일 때
npm i react-hook-form
# 지원하지 않는 리액트 버전일 때
npm i react-hook-form --legacy-peer-deps
리액트에서 일반 폼을 작성하려면 신경 쓸 부분이 많다. 각 input
값에 대한 useState
와 onChange
를 작성하고, submit
에서는 여러 검증 작업 코드를 넣어야 한다. 사용자가 필수 사항을 제대로 입력했는지, 양식에 맞게 작성했는지 등등. 검증에 적합하지 않을 시 보여줄 error
에 대한 useState
도 남았다. 사용자 경험을 만족시키려는 form
을 만들기 위해서는 매우 복잡한 절차를 거쳐야 한다.
import React, { useState } from "react";
export default function Forms() {
const [email, setEmail] = useState("");
const [pwd, setPwd] = useState("");
const [formErrors, setFormErrors] = useState("");
const [emailErrors, setEmailErrors] = useState("");
const [pwdErrors, setPwdErrors] = useState("");
const onEmailChange = (e: React.SyntheticEvent<HTMLInputElement>) => {
const {
currentTarget: { value },
} = e;
setEmailErrors("");
setEmail(value);
};
const onPwdChange = (e: React.SyntheticEvent<HTMLInputElement>) => {
const {
currentTarget: { value },
} = e;
setPwdErrors("");
setPwd(value);
};
const onSubmit = (e: React.SyntheticEvent<HTMLFormElement>) => {
e.preventDefault();
if (email === "" || pwd === "") {
setFormErrors("빈 값이면 안 된다.");
}
if (!email.includes("@")) {
setEmailErrors("이메일은 @를 포함해야 한다.");
}
if (pwd.length < 8) {
setPwdErrors("비밀번호는 8자리 이상!");
}
};
return (
<form onSubmit={onSubmit}>
<input
value={email}
onChange={onEmailChange}
type="email"
placeholder="Email"
required
/>
{emailErrors}
<input
value={pwd}
onChange={onPwdChange}
type="password"
placeholder="Password"
required
/>
<input type="submit" value="Create Account" />
{formErrors}
</form>
);
}
간단하게 이메일과 비밀번호만 입력하는 폼임에도 코드가 많이 길어졌다. 여기에 CSS 작업이나 기타 다른 검증 및 입력 요소를 추가한다면 코드는 매우매우 길어지고 복잡해질 것이다.
React Hook Form
의 useForm
을 사용하면 기나긴 state 코드를 축약할 수 있다.
import { useForm } from "react-hook-form";
export default function Forms() {
const { register } = useForm();
return (
<form>
<input
{...register("email")}
type="email"
placeholder="Email"
required
/>
<input
{...register("password")}
type="password"
placeholder="Password"
required
/>
<input type="submit" value="Create Account" />
</form>
);
}
const { register } = useForm();
단 한 줄로 onChange
와 value
를 대신한다.
form
에 어떤 값이 입력되었는지 보려면 watch
메서드를 사용한다.
const { watch } = useForm();
console.log(watch());
html의 required
는 빈 입력을 막아주지만, 검사 내에서 속성을 지우거나 해당 속성을 지원하지 않는 브라우저에서는 동작하지 않는다. 때문에 Javascript내에서 작동하는 것이 안전하다.
import { useForm } from "react-hook-form";
export default function Forms() {
const { register, /handleSubmit/ } = useForm();
const onValid = () => {
console.log("유효옷!");
};
const onInvalid = () => {
console.log("무효옷!");
};
return (
<form onSubmit={handleSubmit(onValid, onInvalid)}>
<input
{...register("email", /{required: true}/)}
type="email"
placeholder="Email"
required
/>
<input
{...register("password", /{required: true}/)}
type="password"
placeholder="Password"
required
/>
<input type="submit" value="Create Account" />
</form>
);
}
/
로 묶은 부분이 입력 상태를 확인하는 부분이다. {required: true}
는 빈 입력을 허용하지 않는다.
handleSubmit
은 form의 submit을 관리하는 함수로, 기본적으로 event.preventDefault()
기능을 가지면서 2개의 함수 인자를 받는다. onValid
와 onInvalid
로, 전자는 form이 유효할 때 동작하고, 후자는 유효하지 않을 때 동작한다. 이 함수들은 register
에 입력되어 있는 규칙에 따른다. 위의 예로, 만약 내용이 없는 form을 제출한다면, "무효옷!"이 출력될 것이다. 모두 입력했다면 "유효옷!"이 출력된다.
typescript
를 사용한다면 데이터 타입을 정할 수 있다.
interface LoginForm {
password: string;
email: string;
}
export default function Forms() {
const { register, handleSubmit, /formState: { errors }/ } = useForm<LoginForm>();
const onValid = (data: LoginForm) => {
console.log("im valid");
};
const onInvalid = (errors: FieldErrors) => {
console.log("im invalid");
};
return (
<form onSubmit={handleSubmit(onValid, onInvalid)}>
{...children}
{errors.email?.message}
</form>
);
}
발생한 에러를 화면에 표시할 때는 formState: { errors }
를 이용한다.
// reqired
required: "이메일은 필수 입력 사항입니다.",
// minLength
minLength: {
message: "이름은 최소 2글자 이상이어야 합니다.",
value: 2,
},
// maxLength
maxLength: {
message: "이름은 최대 5글자 이하여야 합니다.",
value: 5,
},
// validation
validate: {
notMail: (value) =>
/[a-z0-9._%+-]+@[a-z0-9.-]+.[a-z]{2,3}$/.test(value) || "이메일 양식을 지켜라",
},
useForm
이 지원하는 프로퍼티 중 mode
는 form 제출 전에 유효성 검사를 실행한다.
onBlur
는 입력이 끝난 양식이 규칙에 맞지 않을 경우 곧장 실행되고, 수정되면 바로 지워진다. onChange
는 form이 변할 때마다 규칙을 검사한다.이 외의 유용한 api는 useForm | React Hook Form에서 확인 가능하다.