-
React - react hook form개발 2022. 3. 31. 23:32
학습목표
react-hook-form 패키지를 통해서 회원가입, 로그인 등 폼 양식을 작성하는 방법에 대해 알아보자.
React Hook Form 이란
const Signup = (props) => { const {history} = props; //nickname, id, pwd const [nickname, set_nickname] = useState(""); const [id, set_id] = useState(""); const [pw, set_pw] = useState(""); const [pwCheck, set_pwCheck] = useState(""); //err message const [err_nickname, setErr_nickname] = useState(""); const [err_id, setErr_id] = useState(""); const [err_pw, setErr_pw] = useState(""); const [err_pwCheck, setErr_pwCheck] = useState(""); const [err_, setErr_] = useState(""); const [err_iddouble, setErr_iddouble] = useState(""); const [ok_iddouble, setOk_iddouble] = useState(""); const [err_namedouble, setErr_namedouble] = useState(""); const [ok_namedouble, setOk_namedouble] = useState(""); const [double_btn, setDouble_btn] = useState(true); const [double_btn2, setDouble_btn2] = useState(true); //disabled btn const [disBtn, setDisBtn] = useState(true); ...생략..
useState를 사용한 회원가입 폼을 작성 하려면 각 필드의 상태값을 제어하기위해 많은 useState 함수를 사용해야하는 경우가 있다. 이런 방법은 직관적인 방법이긴 하지만 반복되는 코드와 상태값으로 인해 코드량이 많고 유지보수가 어려울 수가 있다.
React Hook Form은 이러한 폼 양식을 작성 할때 상태관리 뿐만 아니라 에러핸들링, 유효성 검사, 속성 옵션 지정 등 많은 인터페이스를 지원하여 쉽게 폼 양식을 작성 할 수 있도록 도와주는 패키지이다.
이 패키지는 리액트를 사용하는 많은 개발자들에게 인기가 있으며 패키지 용량도 776kb로 적은 편에 업데이트도 활발히 이루어져 굉장히 유용한 패키지라고 할 수 있다.
사용방법
이제부터 기본적인 사용법에 대해서 하나씩 알아보도록 하자.
1. 설치하기
npm install react-hook-form
2. register
register는 비제어 컴포넌트를 Hook과 연결하여 값이 검사될 수 있도록 만들고 폼 제출 시 한꺼번에 모아지도록 도와준다. 다음 코드에서 react-hook-form로 부터 불러온 useForm() 함수에서 제공하는 register를 살펴보자.
import styles from "../styles/Home.module.css"; import { useForm } from "react-hook-form"; export default function Home() { const { register, handleSubmit } = useForm(); const onSubmit = (data) => console.log(data); return ( <form className={styles.form} onSubmit={handleSubmit(onSubmit)}> <label>Email</label> <input name="email" type="email" {...register("email", { required: true, pattern: /^\S+@\S+$/i })} /> ..생략..
register는 회원가입을 위해 사용자로부터 email 정보를 입력받는 input 요소의 값이 제출 시 onSubmit 함수의 매개변수로 접근 가능하도록 등록해준다. submit 동작에 대한 자세한 내용은 아래에서 다시 알아보자.
input 요소의 속성값으로 적용된 register 는 첫번째 인자로 어떠한 name 값의 요소에 등록될 지 작성한다.
다시 말해, register와 요소 등록을 위한 key로 name 속성이 반드시 필요하다.
{...register("email", { required: true, pattern: /^\S+@\S+$/i })}
2. 유효성 검사
{ required: true, pattern: /^\S+@\S+$/i }
두번째 인자로 옵션값을 객체를 할당 할 수 있는데 유효성 검사를 위한 조건을 입력 할 수 있다.
React Hook Form에서 지원하는 폼 유효성 검사 방식은 다음과 같다.
- required
- min
- max
- minLength
- maxLength
- pattern
- validate
3. 에러 핸들링
폼 안의 에러를 보여주는 errors 객체를 사용하여 유효성 조건에 통과하지 못할 경우의 UI를 쉽게 렌더링 할 수 있다.
const { register, formState: { errors }, handleSubmit } = useForm(); return ( <form className={styles.form} onSubmit={handleSubmit(onSubmit)}> <label>Email</label> <input name="email" type="email" {...register("email", { required: true, pattern: /^\S+@\S+$/i })} /> {errors.email && <p>This email field is required</p>} ...생략... )
errors 객체는 register로 등록된 key값으로 해당 필드의 에러 여부를 참조 할 수 있다.
만약 해당 필드의 세부 속성값에 관한 에러 핸들링을 하고자 할 경우에는 다음과 같이 type 속성에 접근하여 세부적인 에러 핸들링을 할 수 있다.
<label>Password</label> <input name="password" type="password" autoComplete="new-password" {...register("password", { required: true, minLength: 6 })} /> {errors.password && errors.password.type === "required" && ( <p>This password field is required</p> )} {errors.password && errors.password.type === "minLength" && ( <p>Password must have at least 6 characters</p> )}
패스워드 입력 시 필수값과 최소 입력 자리수를 각각 따로 핸들링하여 에러문구를 보여주고자 할 때 유용하게 사용 할 수 있다.
4. watch와 useRef를 통한 패스워드 중복확인
일반적인 회원가입 양식에 필수적으로 등장하는 기능으로 1차로 입력한 패스워드를 재확인하는 UI에 사용될 수 있는 기능을 제공한다.
먼저 watch에 대해서 알아보자.
watch는 register로 등록한 필드의 값에 접근 할 수 있게 한다.
한국말로 조금 더 쉽게 표현하자면 등록된 필드값을 관찰하게 하는것이다.
const { register, formState: { errors }, handleSubmit } = useForm(); return ( <form className={styles.form} onSubmit={handleSubmit(onSubmit)}> <label>Email</label> <input name="email" type="email" {...register("email", { required: true, pattern: /^\S+@\S+$/i })} /> {errors.email && <p>This email field is required</p>} ...생략... )
가장 처음으로 등록한 email 요소는 email이라는 key값으로 input 요소의 name="email"과 연결되어있다.
만약 사용자가 이메일을 입력할때 값을 콘솔에 받아보려면 이전에 하던 방식으로
useState() 나, useRef()로 상태에 접근하여 value에 접근 할 수 있을것이다.
하지만 React Hook Form은 이런 작업을 간단히 watch 함수를 통해 해결 할 수 있다.
const { register, formState: { errors }, handleSubmit, watch } = useForm(); return ( <form className={styles.form} onSubmit={handleSubmit(onSubmit)}> <label>Email</label> <input name="email" type="email" {...register("email", { required: true, pattern: /^\S+@\S+$/i })} /> {errors.email && <p>This email field is required</p>} ...생략... )
먼저 useForm에서 지원하는 watch 함수를 선언하고
const emailWatch = watch("email"); console.log(emailWatch); return ( ...생략... )
watch("register로 등록한 key값") 을 할당하면 해당 요소를 지속적으로 관찰하는 상태에 접근 할 수 있다.
다음은 useRef를 사용해 비밀번호 재확인을 어떻게 하는지 알아보자.
useRef는 React에서 제공하는 hook이다. real dom에 접근하여 요소의 상태를 확인 할 수 있는데
이렇게 접근된 값은 컴포넌트의 라이크 사이클 동안 유지되고 값이 변하여도 리렌더링이 되지 않는다는 특징도 있다.
그럼 이제 비밀번호 재확인 요소에 값을 1차 비밀번호와 비교해 유효성 검사를해서 현재 재확인된 비밀번호가 1차 비밀번호와 같은지를 비교해보자.
<label>Confirm</label> <input name="password_confirm" type="password" autoComplete="new-password" {...register("password_confirm", { required: true, validate: (value) => value === password.current, })} /> {errors.password_confirm && errors.password_confirm.type === "required" && ( <p>This password_confirm field is required</p> )} {errors.password_confirm && errors.password_confirm.type === "validate" && ( <p>The passwords do not match</p> )}
password_confirm이라는 name값을 갖고있는 input 요소는 register 옵션 값으로 validate라는 속성이 적용되어있다.
{...register("password_confirm", { required: true, validate: (value) => value === password.current, })}
validate 에는 함수가 지정되어 있는데 매개변수로 제공하는 value값이 현재 재확인 값으로 입력되는 현재 값이다.
그리고 그 함수의 결과로 현재 값과 password.current 값이 같은지의 여부를 리턴하고 있다.
value === password.current
password.current 부분이 바로 useRef() 를 사용하여 현재 1차 비밀번호의 값을 참조해 재확인 비밀번호와 1차 비밀번호의 값을 비교하고있는것이다.
우리는 앞서 watch를 통해서 관찰하고 싶은 요소를 register에 등록된 key값을 통해 확인 할 수 있었다.
watch("password")를 통해서 관찰되고 있는 password값을 current 속성에 할당하여 validate 에서 입력된 재확인값과 비교 할 수 있다.
const password = useRef(); password.current = watch("password"); return ( <form className={styles.form} onSubmit={handleSubmit(onSubmit)}>
4. handleSubmit 을 통해 제출값 확인하기
const { register, formState: { errors }, handleSubmit, watch, handleSubmit } = useForm(); const onSubmit = (data) => console.log(data); return ( <form className={styles.form} onSubmit={handleSubmit(onSubmit)}>
마지막으로 handleSubmit은 form 요소의 onSubmit 이벤트에 등록해 매개변수로 사용자가 실제로 실행할 로직을 할당 할 수 있다.
할당된 onSubmit 함수는 간단히 form이 제출될때 넘어오는 data값만 log를 찍는 동작을 한다.
실제로 제출을 해보자.
정말 깔끔하게도 요소의 name값을 key로 사용하여 입력된 값들을 value로 예쁘게 객체화하여 보여주고있다.
이렇게 간단하게 작성만해도 우리가 회원가입시 원하는 정보를 정리해서 받아 올수 있는것이다.
실제로 회원가입을 로직을 작성한다면 받아온 데이터를 api로 보내주는 추가 로직을 작성한다면 간단히 처리 가능할 것이다.
const onSubmit = (data) => { // ..회원가입.. axios.post('/api/signup', {data}) };
마무리
react hook form을 알기 전에는 useState를 하나하나 만들어 각 상태를 제어하려고 애를 썻었었다.
물론 hook을 사용해서 각각의 상태를 제어하는것이 나쁜방법은 아니지만 코드량이 방대해지고
코드 중복을 줄이려고 노력했을때를 생각해보면 react hook form은 상당히 효과적인 패키지인것 같다.
다만 업데이트가되어 사용법이 조금씩 달라질수도있겠지만 프로젝트에서 버전을 잘 유지하여 사용하면 큰 문제가 될것 같지는 않다.
(최신 react hook form 방식을 사용해야한다면 내 뇌를 업데이트 해야겟지..)
그리고 에러핸들링이 참 쉬운것같다. 자주 써보고 다른 기능은 어떤것이 있는지 더 알아볼 필요가 있겠다.
갑분 비와이 '개발' 카테고리의 다른 글
TIL - Mac 업로드 파일 한글 깨짐 (자모분리현상) (0) 2022.04.19 JS - Map (0) 2022.04.13 TIL - CSS Module (0) 2022.03.28 TIL - Next.js 연습 프로젝트 #2 (0) 2022.03.20 TIL - Recoil 기초 튜토리얼 (0) 2022.03.18