react-hook-form은 사용하기 쉬운 유효성 검사를 통해 성능이 뛰어나고 유연하며 확장 가능한 form이다.
// Less code (c)
// Better validation(c)
// Better Erros (set, clear, display)(c)
// Have control over inputs(c)
// Dont deal with events (c)
// Easier Inputs (c)
아래의 두 코드를 보며 비교해보자!🤔
export default function Forms() { const [username, setUsername] = useState(""); const [email, setEmail] = useState(""); const [password, setPassword] = useState(""); const [formErrors, setFormErrors] = useState(""); const [emailError, setEmailError] = useState(""); const onUsernameChange = (event: React.SyntheticEvent<HTMLInputElement>) => { const { currentTarget: { value }, } = event; setUsername(value); }; const onEmailChange = (event: React.SyntheticEvent<HTMLInputElement>) => { const { currentTarget: { value }, } = event; setEmailError(""); setEmail(value); }; const onPasswordChange = (event: React.SyntheticEvent<HTMLInputElement>) => { const { currentTarget: { value }, } = event; setPassword(value); }; const onSubmit = (event: React.SyntheticEvent<HTMLFormElement>) => { event.preventDefault(); //dev를 위해 새로고침을 막음 if (username === "" || email === "" || password === "") { setFormErrors("All fields are required"); } //프론트엔드에서 minLength나 required 등을 설정해도, 개발자도구에서 지울 수 있기때문에 //이렇게 막아놔야함. 하지만 이것은 너무 비효율적이라 react-form-hook을 사용함 if (!email.includes("@")) { setEmailError("email is required"); } }; return ( <form onSubmit={onSubmit}> <input value={username} onChange={onUsernameChange} type="text" placeholder="Username" required minLength={5} /> <input value={email} onChange={onEmailChange} type="email" placeholder="Email" required /> {emailError} <input value={password} onChange={onPasswordChange} type="password" placeholder="Password" required /> <input type="submit" value="Create Account" /> </form> ); }
import { FieldErrors, useForm } from "react-hook-form"; interface LoginForm { username: string; password: string; email: string; setErrors ?: string //errors는 required가 아님. } export default function Forms() { const { register, handleSubmit,watch,formState: { errors },setValue, setError,reset, resetField, //formState는 errors를 사용할 수 있음. 이걸로 errors.~~.message를 화면에 출력가능 //reset은 onValid 와 같은 함수에 reset()을 넣으면 모든 form이 초기화되는 것이다. //resetField는 특정 필드만 초기화 } = useForm<LoginForm>({ mode: "onChange", //onChange로 하면 submit버튼을 누르지 않아도 유저가 값을 입력하는 순간 유효하지 않으면 실시간으로 출력됌 //onBlur, onSubmit 등등 여러 종류가 있음 }); //handleSubmit은 onValid(form이 유효할 때 실행되는 함수)와 onInValid(form이 유효하지 않을 때 실행되는 함수) 두 가지 함수를 받을 수 있다. console.log(watch()); //input에 입력되는 값이 그대로 console.log됌 const onValid = (data: LoginForm) => { console.log("im valid bby"); setError("setErrors", {message : "Backend Error"}) //setError는 특정한 필드에 관한 에러가 아니더라도 에러를 설정할 수 있게 해주는 것 }; const onInvalid = (errors: FieldErrors) => { console.log(errors); }; setValue("username", "hello"); //username input에 value를 hello로 넣어준다. 직접 value를 설정 return ( {errors.setErrors?.message} <form onSubmit={handleSubmit(onValid, onInvalid)}> <input {...register("username",{ required: "Username is required", //required 다음에 적은 내용이 onInValid에서 errors.message에 들어간다. minLength: { message: "The username should be longer than 5 chars.", value: 5, },)}//errors.type에 어떤 validation이 유효하지 않은지 볼 수 있다. //username이 key, value가 되는 것 //form에 handleSubmit을 넣고 이렇게 required 와 같은 validation을 사용하면 해당 input이 유효하지 않을 때, 실행을 막아준다. type="text" placeholder="Username" /> <input {...register("email", { required: "Email is required", validate: { notGmail: (value) => !value.includes("@gmail.com") || "Gmail is not allowed", }, //notGmail이라는 validation을 추가하는 것. 이메일주소에 gmail이 들어가 있으면, errors.email.message에 들어감. })} type="email" placeholder="Email" classname={`${Boolean(errors.email?.message) ? "border-red-500" : ""}`} //에러 메세지가 있으면 border 색을 변하게 하는등 여러 가지 custom 가능 /> {errors.email?.message} ................. ```
다만 input의 component를 만들고, 불러와서 사용한다면 다음과 같이 사용해야 한다.
<Input register={register("email", { required: true, })} name="email" label="Email address" type="email" required />