📌 react-hook-form
react-hook-form은 React 기반의 폼 관리 라이브러리로, 폼 상태 관리와 폼 유효성 검사를 처리하기 위한 간단하고 효율적인 방법을 제공한다.
react-hook-form을 사용하면 폼 요소의 값이나 상태 변경에 대한 이벤트를 관리하기 위해 명시적인 이벤트 핸들러를 작성할 필요 없이, 단순히 hook만을 사용하여 폼 관련 데이터를 추적하고 업데이트할 수 있다.
간편한 API
react-hook-form은 사용하기 쉽고 직관적인 API를 제공하여 복잡한 폼 로직을 보다 단순하고 직관적이게 해준다. 필요한 기능을 간단히 훅 함수로 호출하고, 컴포넌트 내에서 필요한 상태와 메소드를 사용할 수 있다. 이를 통하여 개발자는 많은 부분을 직접 구현할 필요 없이 더욱 빠르고 효과적인 폼 개발에 집중할 수 있게 된다.
성능 최적화
react-hook-form은 성능에 중점을 두어 최적화되어 있다. 입력 필드 값의 변화를 추적하는 "상태"대신 각 입력 필드의 참조를 사용하여 불필요한 리렌더링을 방지하고, 가상 DOM의 업데이트를 최소화한다. 이는 대규모 폼이나 복잡한 유효성 검사 로직이 필요한 폼에서 특히 유용하다.
유연성과 확장성
react-hook-form은 자체적으로 유효성 검사를 지원하며, yup이나 joi 같은 외부 유효성 검사 라이브러리와 통합할 수도 있다. 또한 커스텀 훅을 사용하여 개발자가 필요한 로직을 보다 쉽게 작성하고 재사용할 수 있도록 지원한다.
register
: ref로 사용되는 함수로 입력 필드를 react-hook-form에 등록하고 변경 사항에 대해 값을 추적한다.
handleSubmit
: form을 서버로 제출할 때 사용한다.
errors
: 유효성 검사 실패 시 해당 필드의 에러 메시지를 포함한다.
setValue
: 동적으로 입력 필드의 값을 설정할 수 있다. 에러가 발생하거나, 에러를 바로잡거나 할 때 렌더링 되어 불필요한 리렌더링을 피할 수 있다.
watch
: 실시간으로 입력 필드에 입력된 값을 관찰하고 그 값을 반환한다. 렌더링 할 대상을 결정할 때 유용하다.
getValues
: 입력 필드의 값을 읽을 때 사용한다. watch와는 다르게 리렌더링을 일으키거나 입력값의 변화를 구독하지 않는다.
control
: Controller 컴포넌트를 사용하기 위해 만들어 졌다. 제어되는 컴포넌트를 react-hook-form에 등록하기 위한 메소드가 포함되어 있다.
formState
: 말 그대로 폼 상태에 관한 객체로 폼에서 발생한 에러나 제출 여부, 값 유효성 등의 세부적인 상태를 확인할 수 있다.
required
: 필수 여부min
: 최소값max
: 최대값minLength
: 문자열 최소 길이maxLength
: 문자열 최대 길이pattern
: 정규식 검사validate
: 직접 작성한 유효성 검사 함수import React from "react";
import { useForm } from "react-hook-form";
const Example = () => {
const { register, handleSumbit } = useForm();
const onSubmit = (data) => {
console.log(data);
// 회원가입 로직...
}
const onError = (error) => {
if (error?.email) {
return alert(error?.email?.message);
} else if (error?.password) {
return alert(error?.password?.message);
} else if (error?.name) {
return alert(error?.name?.message);
} else if (error?.phone) {
return alert(error?.phone?.message);
}
}
return (
<div>
<div>
<label>이메일</label>
<input
{...register("email", {
required: "이메일을 입력해 주세요.",
pattern: {
value: RegExp(/^[a-zA-Z0-9+-\\_.]+@[a-zA-Z0-9-]+\\.[a-zA-Z0-9-.]+$/),
message: "이메일 형식에 맞게 입력해 주세요."
}
})}
/>
</div>
<div>
<label>비밀번호</label>
<input
type="password"
{...register("passowrd", {
required: "비밀번호를 입력해 주세요.",
pattern : {
value: /^.*(?=^.{8,20}$)(?=.*\d)(?=.*[a-zA-Z])(?=.*[\x20-\x2F\x3A-\x40\x5B-\x60\x7B-\x7E]).*$/i,
message: "비밀번호 형식에 맞게 입력해 주세요."
},
minLength: {
value: 8,
message: "비밀번호는 8자 이상으로 입력해 주세요.",
},
})}
/>
</div>
<div>
<label>이름</label>
<input {...register("name", { required: "이름을 입력해 주세요." })} />
</div>
<div>
<label>휴대폰번호</label>
<input {...register("phone", { required: "휴대폰번호를 입력해 주세요." })} />
</div>
<button onClick={handleSubmit(onSubmit, onError)}>회원가입</button>
</div>
)
};