회사 프로젝트에서 form을 많이 사용하고 있는데 유효성 검사를 할 때 번거로움이 있었다
react hook form을 사용하면 이를 단순화 시킬 수 있으며, 다른 라이브러리에 비해 리랜더링 수가 적고 로딩속도가 빠르다
npm install react-hook-form
export default function App() {
return (
<form>
<input type="text" placeholder="first name" />
<br />
<input type="text" placeholder="last name" />
<br />
<br />
<button type="submit">submit</button>
</form>
);
}
위와 같은 폼이 있다고 가정을 해보자
react-hook-form은 기본적으로 비제어 컴포넌트와 input을 활용한다
input이 react-hook-form에 의해 비제어 컴포넌트로 동작하기 위해서는 register 함수가 반환하는 값을 컴포넌트의 prop으로 전달받아야 한다
import { FormProvider, useForm, useFormContext } from "react-hook-form";
import { ContentData } from "@customTypes/components/formHokk";
export default function App() {
const formMethod = useForm<ContentData>({
defaultValues: {
firstName: "",
lastName: "",
},
});
const { register } = useFormContext<ContentData>();
return (
<FormProvider {...formMethod}>
<form>
<input
type="text"
placeholder="first name"
{...register("firstName", {
required: "please enter first name",
})}
/>
<br />
<input
type="text"
placeholder="last name"
{...register("lastName", {
required: "please enter last name",
})}
/>
<br />
<br />
<button type="submit">submit</button>
</form>
</FormProvider>
);
}
form element를 formprovider로 감싸고 input을 register로 등록해주면 된다
register는 ref로 사용되는 함수로 입력 필드를 React Hook Form에 등록하고 변경 사항에 대해 값을 추적하며 이 때 사용되는 name은 유니크해야한다
근데 이렇게 사용하면 아래와 같은 에러가 발생한다
form 안에 있는 내용들을 아래와 같이 컴포넌트화 해서 사용하면 에러는 발생하지 않는다
컴포넌트화를 하지 않고 사용하고 싶다면 useFormContext
대신 useForm
을 사용하면 된다
import FormContent from "./FormContent";
import { FormProvider, useForm } from "react-hook-form";
import { ContentData } from "@customTypes/components/formHokk";
export default function App() {
const formMethod = useFormContext<ContentData>({
defaultValues: {
firstName: "",
lastName: "",
},
});
const onSubmitHandling = (data: ContentData) => {
console.log(data);
};
return (
<FormProvider {...formMethod}>
<form onSubmit={formMethod.handleSubmit(onSubmitHandling)}>
{/** 위에 있던 자식들을 그대로 컴포넌트화 **/}
<FormContent />
</form>
</FormProvider>
);
}
handleSubmit은 form을 서버로 제출할 때 사용하는 함수이다
import { ContentData } from "@customTypes/components/formHokk";
import { useFormContext } from "react-hook-form";
export default function FormContent() {
const {
register,
formState: { errors },
} = useFormContext<ContentData>();
return (
<>
<input
type="text"
placeholder="first name"
{...register("firstName", {
required: "please enter first name",
})}
/>
{errors.firstName && <p>{errors.firstName.message}</p>}
<br />
<input
type="text"
placeholder="last name"
{...register("lastName", {
required: "please enter last name",
})}
/>
{errors.lastName && <p>{errors.lastName.message}</p>}
<br />
<br />
<button type="submit">submit</button>
</>
);
}
폼을 제출할 때 유효성 검사를 통과하지 않으면 formState의 errors에 register할 때 required에서 설정한 메세지가 저장된다
값을 정상적으로 입력했다면 아래와 같이 출력되는걸 확인할 수 있다