리액트 웹/앱에서 복잡한 폼 로직을 간단하고 효율적으로 관리/구현 할 수 있도록 도와주는 라이브러리이다.
• 성능 최적화 : 필요한 컴포넌트만 다시 렌더링되므로, 복잡한 폼에서도 좋은 성능을 제공
• 간편한 상태 관리 : 폼 데이터를 관리하기 위한 별도의 상태 관리 컴포넌트 및 변수 생성이 필요없다.
• 유효성 검사 및 에러 처리 : 폼 유효성 검사 및 에러처리를 쉽게 처리할 수 있는 훅(useForm
)을 지원한다.
• 다양한 입력 유형 : 텍스트 입력부터 체크박스, 라디오 버튼, 선택 목록 등 다양한 입력 유형을 지원한다.
• 생산성 향상 : 무엇보다 register, setValue, handleSubmit 등의 함수를 사용하여 복잡한 폼 로직을 구현할 수 있어 편리하다는 것이 제일 큰 장점이다.
• 비제어 컴포넌트: 비제어 컴포넌트를 사용하기 때문에, React의 일관된 상태 관리 패턴을 따르지 않음
npm install react-hook-form
yarn add react-hook-form
<form
onSubmit={() => console.log("submit")}
>
<div className="mt-2">
<input
type="text"
/>
</div>
<button
type="submit"
>
제출
</button>
</div>
</form>
import { useForm } from "react-hook-form";
const {
register,
handleSubmit,
setValue,
formState: { errors },
} = useForm<StoreType>();
useForm 훅에는 다양한 함수가 존재하지만 내가 프로젝트에서 사용한 함수는 다음과 같다.
{...register("storeType", { required: true })}
<form
onSubmit={handleSubmit(async (data) => {
const result = await axios.post("/api/comments", {
...data,
storeId,
});
{errors?.name?.type === "required" && (
<p className="pt-2 text-xs text-red-600">
필수 입력사항입니다.
</p>
)}
// Update a single field
setValue('name', 'value', {
shouldValidate: true, // trigger validation
shouldTouch: true, // update touched fields form state
shouldDirty: true, // update dirty and dirty fields form state
});
<input {...register("firstName", { required: true })} />
<button type="button" onClick={() => resetField("firstName"))}>Reset</button>
<form
onSubmit={handleSubmit(async (data) => {
try {
const result = await axios.post("/api/stores", data);
if (result.status === 200) {
toast.success("맛집을 등록했습니다.");
router.replace(`/stores/${result?.data?.id}`);
} else {
toast.error("다시 시도해주세요.");
}
} catch (e) {
toast.error("데이터 생성 중 문제가 발생했습니다. 다시 시도해주세요.");
}
})}
>
<div className="mt-2">
<input
type="text"
{...register("name", { required: true })}
/>
{errors?.name?.type === "required" && (
<p className="pt-2 text-xs text-red-600">
필수 입력사항입니다.
</p>
)}
</div>
<button
type="submit"
>
제출
</button>
</div>
</form>
: register 함수를 통해 정의한 유효성 검사 규칙에 따라 입력 필드의 값이 유효한지 자동으로 검사하며 다음의 규칙을 지원한다.
required > boolean
: 필드의 값을 반드시 입력해야 함을 나타내는 옵션이다.
<input
{...register("test", {
required: true
})}
/>
min > number
: 필드의 허용되는 최소 값을 나타내는 옵션이다.
<input
type="number"
{...register("test", {
min: 3
})}
/>
max > number
: 필드의 허용되는 최대 값을 나타내는 옵션이다.
<input
type="number"
{...register('test', {
max: 3
})}
/>
minLength > number
: 필드의 허용되는 값의 최소 길이를 나타내는 옵션이다.
<input
{...register("test", {
minLength: 1
})}
/>
maxLength > number
: 필드의 허용되는 값의 최대 길이를 나타내는 옵션이다.
<input
{...register("test", {
maxLength: 2
})}
/>
pattern > RegExp
: 필드의 입력에 대한 정규식 패턴이다.
<input
{...register("test", {
pattern: /[A-Za-z]{3}/
})}
/>
validate > Function | Object
: Custom Validation 이 필요한 경우 콜백 함수를 인수로 전달하여 유효성을 검사할 수도 있고, 콜백 함수의 개체를 전달하여 모든 유효성을 검사할 수도 있는 옵션이다. 이 함수는 속성에 포함된 다른 유효성 검사 규칙에 의존하지 않고 자체적으로 실행된다.
<input
{...register("test", {
validate: (value, formValues) => value === '1'
})}
/>
// object of callback functions
<input
{...register("test1", {
validate: {
positive: v => parseInt(v) > 0,
lessThanTen: v => parseInt(v) < 10,
validateNumber: (_, values) =>
!!(values.number1 + values.number2),
checkUrl: async () => await fetch(),
}
})}
/>
💡
참조