본문 바로가기
Front-end/React

리액트 상태관리 라이브러리 React-Hook-Form

by 꼬바리 2023. 3. 16.

기존에는 리액트의 상태를 useState 와 onChang 를 사용 하였다.

상태관리 툴이나 라이브러리 없이 상태를 관리 해왔다.

장점은 직관적이며, 데이터의 validation , 데이터변환 등

단점은 한개의 변환시 모든 데이터, 변경하시않은 상태도 다시 랜더링 된다는것 (치명적)

 

 

사실 위 코드도 나는 형식을 잘잡아놔서 충분히 사용할수 있지만

개발자는 유행하는건 배우고 따라해봐야하니까 (귀찮)

작년말 2022년부터 현재 2023년까지 상태관리 라이브러리 "react hook form"의 사용자 수가 증가 했다.

 


react hook form

 

😎 install

npm i react-hook-form

😎 import

import { useForm } from "react-hook-form";

 

라이브러리 미사용 useState에 상태값을 직접 넣어줬다. ** 또한 훅폼 사용전엔 form을 사용해 주지 않았다 **

const [joinInfo , setJoinInfo] = useState({
        organizationCd : '',
        position:'',
        userName:'',
        userId: '',
        userPwd: '',
        userPwdChk: '',
        createSystemCd: 'PORTAL'
    });

 

 

Hook Form 사용시,  (코드시 좀더 길어진거 같지만 꺼내쓰고 뭐하고 다 하면된다)

관리할 데이터들 (input)을 폼태그 안에 넣어줘야한다.

당연히 버튼이 아닌 submit

<form onSubmit={handleSubmit(onSubmit)}>
</form>
const onSubmit = async (data) =>{ 
	await new Promise((r) => setTimeout(r, 1000));      //중복제출 방지 -> 1초 텀
	// console.log(data)
}

더블 클릭등 중복제출 방지를 위한 time 설정도 필요하다.

예전 스트링 같다.

 

const { register, watch, handleSubmit
        , reset, setValue, getValues, setError, setFocus , clearErrors 
        , formState: { errors, isSubmitting, isDirty, dirtyFields, } 
    } = useForm({
        mode: 'onSubmit' , 
        defaultValues: {
            organizationCd : '',
            position:'',
            userName:'',
            userId: '',
            userPwd: '',
            userPwdChk: '',
            createSystemCd: 'PORTAL'
        } ,
      });

 

😎 configuration 옵션

1 mode
     - mode 와 defaultValues 를 가장 많이 활용
     - mode 옵션은 validation 전략을 설정
     - mode는 form의 유효성 검사를 어느 동작때 시행할지 설정하는 props
     - mode : onSubmit (default) , onChange, onBlur, onTouched , all
     - [주의] mode : onChange 다수의 리렌더링 발생
     - onBlur 사용자가 submit 버튼을 누르기 전 입력 값이 유효한지 미리 표시
     - onBlur 이벤트가 발생할때마다 validation이 실행
2 defaultValues
     - form 에 기본 값 제공
     - 기본값을 미제공시 input의 초기값은 undefined
3 register
      - 컨트롤 할 폼객체를 리턴받음
      - register 를 통해 input태그 핸들링
      - required, min, max, minLength, maxLength, pattern, validate, disabled, onChange, value ...
      - value 초기 입력값
4 formState
      [errors]
      - 에러에 대한 정보는 formState 객체의 errors 에 들어있다.
      - 에러 미존재시 해당 객체 빈 객체

      [submitCount]
      - submit한 횟수를 알수있음

      [isDirty]
      - 사용자가 defaultValues 를 수정한 경우 true

      [dirtyFields]
      - 기본 값에 수정된 필드값이 담긴 객체
      - dirtyFields 를 사용하기 위해선 defaultValues세팅 필수

      [touchedFields]
      - 사용자에 의해 수정된 필드가 담긴 객체

      [isValid]
      - 에러 확인
5 watch
      - 값을 추적 1 method
      - 입력값 추적 -> 반환 -> 해당 값에 따라서 리렌더링
      - 폼에 입력된 값을 구독하여 실시간으로 체크
6 getValues
      - 값을 추적 2 method
      - 반환 -> No 추적 -> No 리랜더링
7 reset
      - 해당 폼으로 create 기능 뿐만 아니라 edit 기능까지 커버
      - 수정 페이지

 

데이터를 꺼내쓰는 방법은 여러가지가 있지만

watch를 사용하여 원하는 데이터를 확인 가능하다.

const { organizationCd , position , userName , userId , userPwd ,userPwdChk } = watch();

 

 

데이터를 onChang 하여 연결해주는것이 아니라

register 로 데이터를 연결 해준다.

<div>
    <label className='required'>아이디</label>
    <input 
        type="text" 
        name="userId"
        className='id-input'
        placeholder="영문+숫자 최대 5~8자"
        autoComplete='off'
        {...register("userId", { 
            required: '아이디을 입력해주세요.' , 
            minLength : {
                value: 5 , 
                message : '최소 5자 이상 입력해주세요'
            } , 
            maxLength : {
                value: 8 , 
                message : '최대 8자 이하 입력해주세요'
            } , 
            pattern: {
                value: /^[A-za-z0-9]{5,8}$/ ,
                message: '영문+숫자 최대 5~8자' ,
            } ,
        })}
    />
    <button className='btn-blue' type='button' onClick={onDoubleCheckID}>중복 확인</button>
    {
         errors.userId ? <p className='error'>{errors.userId.message}</p>
         : doubleCheckID ? <p className='success'>사용 가능한 아이디 입니다.</p> 
         : <p role="alert">중복 확인이 필요합니다.</p> 
    }
</div>

위 코드는 아이디 값을 받아오고 에러를 어떻게 뱉는지에 관한 코드이다.

에러메세지의 대한 반응이 정말 신세계였다.

 

onChange로 일일이 등록 안해줘도 되니까 더 직관적이고 쉽지만,

실제 개발을 하다보면 수많은 변수가 생긴다.

 

어떠한 필드는 스페이스바 금지, 

혹은 중복체크, 데이터형식이 아닌 조건이 또 추가될수 있다.

공홈과 오버플로우를 헤매며 적용해보았다.

<div className="">
    <label className='required'>성명</label>
    <input 
        type="text" 
        name="userName"
        placeholder="성명"
        autoComplete='off'
        {...register("userName", {
            required: '성명을 입력해주세요.' , 
            minLength: {
                value : 2 , 
                message : '최소 2글자 이상 입력 해주세요.'
            } , 
            maxLength : {
                value: 10 , 
                message : '최대 10자 이하 입력해주세요'
            } , 
            onChange : (e) => {
                setValue('userName' , e.target.value.replace(NotSpace,''))
            } , 
            validate : (e) => {} ,
        })}
    />
    {errors.userName ? <p className='error'>{errors.userName.message}</p> : <p role="alert"></p>}
</div>

아이디 , 이름 값을 받은 코드

이름 의 경우 onChange에 setValue라는 함수를 사용했다.

NotSpace 는 내가 가지고있는 공통 정규식을 불러온것 그대로적용하면 오류

input자체에 onChange를 걸어준게 아니라 훅폼 내의 onChange이다. 주의 필요

 

 

기본적인 훅폼 사용법은 인터넷에 많이 공유 되어있지만

많은 벨리데이션을 추가된 예제나 폼이 없어서 쉬운 사용법 대비 적용에 시간투자를 조금 했다.

 

reset과 수정에 대한 코드도 업로드 하겠다.

728x90
반응형

댓글