⚠️ 본 포스트는 프로젝트 기록용으로, 개념에 대한 설명이나 라이브러리의 특성에 대해 설명하지 않습니다.
React에서 상태값을 관리할 때 useState
를 주로 사용한다. 아래의 코드는 useState를 사용하여 password 값을 관리하는 예시 코드다.
const [password, setPassword] = useState<string>("");
const onChangePassword = (e: React.ChangeEvent<HTMLInputElement>) => {
setPassword(e.target.value);
};
return (
<input
placeholder="******"
type="password"
onChange={onChangePassword}
/>
)
React의 제어 컴포넌트 특성으로, state가 업데이트될 때마다 컴포넌트가 리렌더링이 발생하게 된다. 이로 인해 컴포넌트의 state가 변경되면 props로 전달받은 자식 컴포넌트도 함께 리렌더링이 발생하며, 불필요한 렌더링이 발생할 수 있어 성능에 영향을 줄 수 있다.
import { useForm } from "react-hook-form";
const form = useForm({
defaultValues: {
email: "",
password: "",
},
});
return (
<Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-6">
<FormField
control={form.control}
name="password"
render={({ field }) => (
<FormItem>
<FormLabel htmlFor="password">Password</FormLabel>
<FormControl>
<Input {...field} placeholder="******" type="password" />
</FormControl>
</FormItem>
)}
/>
</form>
)
전체 부분이 리렌더링이 발생하지 않고 변경된 필드만 다시 렌더링 하여 최적화된 것을 확인할 수 있다
회원가입 페이지는 이름, 이메일, 비밀번호 3가지 정보를 입력받고 Create an account
버튼을 눌러서 유효성 체크 후 올바르지 않게 입력한 경우 에러 메시지를 표시한다
Zod는 형식에 맞는 스키마 인스턴스를 생성하고, infer
를 통해 자동 타입 추론이 가능하다.
Zod 스키마를 사용하여 회원가입 페이지 구현
// schema 정의
import * as z from "zod";
export const RegisterSchema = z.object({
name: z.string().min(1, {
message: "Name is required",
}),
email: z.string().email(),
password: z.string().min(1, {
message: "Minimun 6 characters required",
}),
});
// Zod의 infer과 JS의 `typeof` 연산자를 사용해서 이미 정의한 스키마로 부터 타입을 추출
// 정의한 스키마를 zodResolver의 인수로 넣어준다
const form = useForm<z.infer<typeof RegisterSchema>>({
resolver: zodResolver(RegisterSchema),
defaultValues: {
email: "",
password: "",
name: "",
},
});
return(
<Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-6">
<FormField
control={form.control}
name="name"
render={({ field }) => (
<FormItem>
<FormLabel htmlFor="name">Name</FormLabel>
<FormControl>
<Input
{...field}
disabled={isPending}
placeholder="Henry"
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
...
)
불필요한 리렌더링도 발생하지 않고 유효성 체크까지 손쉽게 구현
만약 react-hook-form
과 zod
라이브러리를 사용하지 않고 폼 상태 관리 및 유효성 체크 코드를 작성했다면 렌더링 최적화도 안 되고, 코드가 길어지고 복잡해졌을 것이다
const [formValues, setFormValues] = useState({
email: "",
password: "",
name: "",
});
// 유저가 입력한 값이 유효한지 검사
const [formErrors, setFormErrors] = useState({
email: false,
password: false,
name: false,
});
const validateForm = () => {
if (password.length < 6)
setFormErrors({
...formErrors,
password: "비밀번호는 6자 이상이어야 합니다.",
});
if ()...
};
...
const onChange = (e: React.ChangeEvent<HTMLInputElement>) => {
switch (e.target.name) {
case "email":
setFormValues({
...formValues,
email: e.target.value,
});
break;
case "password":
setFormValues({
...formValues,
password: e.target.value,
});
break;
case "name":
setFormValues({
...formValues,
name: e.target.value,
});
break;
}
};
참고 자료
저는 프로젝트시 React Hook Form으로 유효성 검사도 진행한 경험이 있는데 zod라는 방식도 있군요! 배워갑니다 👍🏻