공식문서 링크 : https://react-hook-form.com/
아주 전통적인 방법으로, form 에 있는 input, button 등에 대한 컨트롤을 하기 위해선 state가 필요하다.
근데 우리 프로젝트 같은 경우에는 약 9개 정도의 input이 필요하다.
그리고 몇 개는 유효성 검사도 필요하다. 그러면 각자 다른 value에 대해 유효성 검사도 해야하지,
저장도하고, 서버에도 보내고 실패하면 거기에 따른 처리도 해줘야한다.
그렇다면 이 것을 모두 생 react 를 구현한다고하면 꽤나 번거로울 것이다.
이 때 사용할 수 있는 것이 이 react-hook-form 이다.
필요한 것은
각각의 사용법에 따른 코드의 예시를 확인해보자.
import ReactDOM from "react-dom"
import { useForm, SubmitHandler } from "react-hook-form"
enum GenderEnum {
female = "female",
male = "male",
other = "other",
}
interface IFormInput {
firstName: string
gender: GenderEnum
}
export default function App() {
const { register, handleSubmit } = useForm<IFormInput>()
const onSubmit: SubmitHandler<IFormInput> = (data) => console.log(data)
return (
<form onSubmit={handleSubmit(onSubmit)}>
<label>First Name</label>
<input {...register("firstName")} />
<label>Gender Selection</label>
<select {...register("gender")}>
<option value="female">female</option>
<option value="male">male</option>
<option value="other">other</option>
</select>
<input type="submit" />
</form>
)
}
control 하고 싶은 input에 {...register("firstName")} 를 적어준다.
이렇게 input에 적으면 폼의 검증과 제출에 모두 값을 사용할 수 있다.
const {
register,
handleSubmit,
formState: { errors, isValid },
} = useForm<LoginDTO>({
mode: "onChange",
});
<form onSubmit={handleSubmit(onSubmit)}>
<input {...register("firstName", { required: true, maxLength: 20 })} />
<input {...register("lastName", { pattern: /^[A-Za-z]+$/i })} />
<input type="number" {...register("age", { min: 18, max: 99 })} />
<input type="submit" />
</form>
<label htmlFor="password" className="text-sm font-medium text-gray-700">
비밀번호
</label>
<input
id="password"
type="password"
placeholder="비밀번호를 입력해주세요"
className="mt-1 w-full border p-2 rounded-lg"
{...register("password", { required: "비밀번호는 필수 항목입니다." })}
/>
{errors.password && (
<span className="text-red-500 text-sm">
{errors.password.message}
</span>
)}
위처럼 정규식 또는 required 프로퍼티를 추가해서 이 value가 필수적일 때
즉 input이 비어있을 때에 대한 message 등을 전달할 수 있다.
이런식으로! 에러 메세지를 전달하고 싶다면 useForm의 formState : { errors} 를 꼭 추가할 것.
const {
register,
handleSubmit,
formState: { errors, isValid },
} = useForm<LoginDTO>({
mode: "onChange",
});
<button
type="submit"
disabled={!isValid}
className={`w-full p-2 rounded-lg ${
isValid
? "bg-blue-600 hover:bg-blue-700 text-white"
: "bg-gray-300 text-gray-500"
}`}
>
로그인
</button>
isValid를 추가해서 input들의 모든 유효성 검사를 통과했을 때 위의 버튼 같이 isValid를 통해 조건문 레이아웃을 설정할 수도 있다!
isValid하나로 state를 확 줄일 수 있는 것이다!
근데 고민이 하나 있다면 너무 많은 input에 대한 처리를 해야되는데 그것은 어렵지 않다.
하지만, 컴포넌트를 어떻게 나눌지 고민하고 있다.
이런 고민에 빠져있다 더 좋은 결과물을 위해서 생각해보자.
⇒ constant를 만들어서 map 돌리는 것으로 결정!
이유 1. 필드들이 크게 다르지 않아서
이유 2. 반복되는 필드를 한 곳에서 관리하기 떄문에 유지보수 하기 쉬워서.
내일 리팩토링 해보자!