[react-hook-form + TypeScript] 리액트 훅 폼 사용법과 타입 주기
오늘은 react-hook-form
의 기본적인 사용법과 타입 주는 방법을 작성해보고자 한다.
바로 본론으로!!
1. 폼으로 입력받을 데이터 타입 정의하기
// SignupForm.tsx
interface FormValue {
name: string
nickname: string
email: string
password: string
password_confirm: string
}
// SignupForm.tsx
interface FormValue {
name: string
nickname: string
email: string
password: string
password_confirm: string
}
회원가입을 하는 SignupForm.tsx
을 작성한다고 쳤을 때 타입스크립트에서는 먼저 회원가입 양식에 들어갈 각 데이터의 타입을 먼저 정의해주어야 한다.
2. useForm 사용하기
import { useForm, SubmitHandler } from "react-hook-form";
const SignupForm: FC = () => {
const { register, handleSubmit, watch, formState: { errors } } = useForm<FormValue>()
return (
// ...
)
}
import { useForm, SubmitHandler } from "react-hook-form";
const SignupForm: FC = () => {
const { register, handleSubmit, watch, formState: { errors } } = useForm<FormValue>()
return (
// ...
)
}
그 다음에는 react-hook-form
에서 import 한 useForm
훅을 사용해서 객체 구조분해 할당으로 register
, handleSubmit
, watch
, errors
등을 꺼낸다.
register
는 리액트훅폼에게, 이 인풋에 대해 이러한 항목을 입력받을 것이라는 것을 등록해준다.handleSubmit
은 리액트훅폼에서 각 항목이 입력되었을 때 submit 이벤트를 처리하는 역할을 한다.watch
는register
한 항목의 변경사항을 추적한다errors
는 유효성이 통과되지 않으면 에러 상태를 내보내준다.
중요한건 여기서 useForm
훅을 실행할 때 제너릭타입으로 <FormValue>
를 넣어줌으로써 입력받을 데이터의 타입들을 리액트훅폼에 전달해준다.
3. 각 항목에 적용하기
import { useForm, SubmitHandler } from "react-hook-form";
const SignupForm: FC = () => {
const { register, handleSubmit, watch, formState: { errors } } = useForm<FormValue>()
const onSubmitHandler: submitHandler<FormValue> = (data) => {
console.log(data)
}
return (
<form onSubmit={handleSubmit(onSubmitHandler)}>
<label>name</label>
<input {...register("name")} />
<label>nickname</label>
<input {...register("nickname")} />
<label>email</label>
<input {...register("email")} type="email" />
<label>password</label>
<input {...register("password")} type="password" />
<label>password_confirm</label>
<input {...register("password_confirm")} type="password" />
</form>
)
}
import { useForm, SubmitHandler } from "react-hook-form";
const SignupForm: FC = () => {
const { register, handleSubmit, watch, formState: { errors } } = useForm<FormValue>()
const onSubmitHandler: submitHandler<FormValue> = (data) => {
console.log(data)
}
return (
<form onSubmit={handleSubmit(onSubmitHandler)}>
<label>name</label>
<input {...register("name")} />
<label>nickname</label>
<input {...register("nickname")} />
<label>email</label>
<input {...register("email")} type="email" />
<label>password</label>
<input {...register("password")} type="password" />
<label>password_confirm</label>
<input {...register("password_confirm")} type="password" />
</form>
)
}
기본적으로 이런 형식으로 작성된다.
각 input 태그에는 {...register("name")}
처럼 속성으로 넣어주는데, 이렇게 하면 등록이 된다. register()
의 인자로는 이전에 작성한 FormValue
인터페이스에 맞게 각 데이터의 이름을 따옴표로 감싼 문자열로 넣어준다.
그럼 이제 각 항목의 데이터는 각 input 태그에 등록되어, 해당 input 은 해당 데이터만을 받게 된다.
그리고 onSubmitHandler
핸들러를 만들어서 타입은 submitHandler<FormValue>
로 작성해주고 모든 항목이 정상적으로 입력이 되었을 때의 처리할 로직을 내부에 작성해준다.
위의 핸들러는 회원가입의 로직이 등록될 것이다.
인자로 들어온 data 에는 register()
가 등록된 input 의 각 value 가 key-value 형태로 들어온다.
<form>
태그의 onSubmit
이벤트에는 바로 onSubmitHandler
를 등록하는게 아니라 리액트훅폼에서 꺼낸 handleSubtmit
의 인자로 넣어서 handleSubmit(onSubmitHandler)
를 걸어준다.
그럼 이제 이 <form>
태그 안에 있는 각 항목이 내가 직접 작성한 조건에 맞지 않으면 submit
이벤트가 발생하지 않는다.
4. 유효성 검증하기
단지 register
로 등록만 하는 것으로는 유효성 검증이 이루어지지 않는다. 이제 register
를 할 때 유효성 검증을 하는 코드를 추가해준다.
import { useForm, SubmitHandler } from "react-hook-form";
const SignupForm: FC = () => {
const { register, handleSubmit, watch, formState: { errors } } = useForm<FormValue>()
const onSubmitHandler: submitHandler<FormValue> = (data) => {
console.log(data)
}
return (
<form onSubmit={handleSubmit(onSubmitHandler)}>
<label>name</label>
<input {...register("name", { requried: true, maxLength: 20 })} />
<label>nickname</label>
<input {...register("nickname", { requried: true, maxLength: 10 })} />
<label>email</label>
<input {...register("email", { required: true, pattern: /^\S+@\S+$/i })} type="email" />
<label>password</label>
<input {...register("password", { required: true, minLength: 6 })} type="password" />
<label>password_confirm</label>
<input {...register("password_confirm", { ... })} type="password" />
</form>
)
}
우선 비밀번호 확인을 의미하는 password_confirm
을 제외하고는 이런 식으로 유효성 검증을 해줄 수 있다.
register()
의 첫번째 인자인 각 데이터항목의 이름 다음으로,
두번째 인자로 객체 형식으로 어떤 유효성 검증을 할지를 적어주면 된다.
우선 각 항목의 경우 모두 필수로 입력되어야 하기 때문에 required: true
를 넣어주었다.
또 이름과 닉네임의 경우 maxLength: Number
로 최대글자 수를 지정해주었고,
비밀번호의 경우는 minLength: Number
로 최소글자 수를 지정해주었다.
이메일은 pattern: RegExp
처럼 정규표현식으로 어떤 패턴을 받을지를 지정해주었다.
비밀번호 확인 유효성 검증하기
비밀번호 확인 (password_confirm) 의 경우 유효성 검증이 조금 추가된다.
import { useForm, SubmitHandler } from "react-hook-form";
const SignupForm: FC = () => {
const { register, handleSubmit, watch, formState: { errors } } = useForm<FormValue>()
// 비밀번호와 비밀번호 확인이 일치하는지 검증하기 위해 "password" input 의 value 를 추적함
const passwordRef = useRef<string | null>(null)
passwordRef.current = watch("password")
const onSubmitHandler: submitHandler<FormValue> = (data) => {
console.log(data)
}
return (
<form onSubmit={handleSubmit(onSubmitHandler)}>
{/* 중략 */}
<label>password_confirm</label>
<input
{...register("password_confirm", {
required: true,
validate: (value) => value === passwordRef.current,
})}
type="password"
/>
</form>
)
}
useRef
훅을 통해서 "password" input 의 입력된 값을 watch("password")
로 추적한다.
그리고 password_confirm 의 유효성 검증에서
validate: (value) => value === passwordRef.current
를 추가함으로써
passwor_confirm 의 value 가 passwordRef.current 와 일치하면 유효성이 검증되는 것으로 한다.
5. 유효성 검증이 통과되지 못한 경우 에러문구 내보내기
useForm
훅을 통해서 errors
객체를 객체 구조분해 할당으로 꺼내왔다.
만약 유효성이 통과되지 못하면 errors.해당데이터
에는 에러의 관한 내용이 담기게 된다.
따라서 만약 errors
객체 안의 내용이 있을 경우 에러문구를 직접 커스텀해줄 수 있다.
import { useForm, SubmitHandler } from "react-hook-form";
const SignupForm: FC = () => {
const { register, handleSubmit, watch, formState: { errors } } = useForm<FormValue>()
// ...
return (
<form onSubmit={handleSubmit(onSubmitHandler)}>
<label>name</label>
<input {...register("name", { requried: true, maxLength: 20 })} />
{errors.name && errors.name.type === "required" && (
<div>이름을 입력해 주세요!</div>
)}
{errors.name && errors.name.type === "maxLength" && (
<div>이름은 최대 20자만 입력할 수 있습니다!</div>
)}
{ /* 중략 */}
</form>
)
}
현재 name
에는 유효성 검증이 2가지 항목이 들어가있다.
필수 입력하라는 required: true
와 최대20자로 제한하는 maxLength: 20
이 있다.
따라서 하나는 errors.name
이 있고 errors.name.type
이 "required" 일 경우 이름을 입력해 달라는 에러문구를 내보내고 있고,
다른 하나는 errors.name
이 있고 errors.name.type
이 "maxLength" 일 경우 이름을 최대 20자만 입력해달라는 에러문구를 내보낸다.
이상 react-hook-form
으로 간단하게 유효성을 검증하고, 타입까지 지정하는 방법을 알아봤다.
리액트훅폼은 굉장히 유용하기 때문에 자주 쓰이고 있는 라이브러리다.
또한 리액트훅폼은 타입스크립트 친화적이기 때문에 따로 @types/...
같은 라이브러리를 추가로 설치할 필요가 없고, 세세한 타입 지정하는 법 또한 공식문서에 잘 나와있다.
react-hook-form 공식문서 with TypeScript
Author And Source
이 문제에 관하여([react-hook-form + TypeScript] 리액트 훅 폼 사용법과 타입 주기), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@ckm960411/react-hook-form-TypeScript-리액트-훅-폼-사용법과-타입-주기저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)