• React

[React] React Hook Form

man_on 2022. 5. 8. 21:42
반응형

 

 

 

     


     

    React Hook Form

     

     

    React Hook Form을 사용하는 이유

    • validation을 쉽게 구현할 수 있다.
    • error를 쉽게 설정하고 초기화 할 수 있다.
    • event를 하나하나 신경쓰지 않아도 된다.
    • 코드의 양을 줄일 수 있다. (반복되는 코드를 줄일 수 있다.)

     

     

     

     

     


     

     

     

     

     

    Form

     

     

     

     

    우선 비교를 위해서 React hook form 없이 기본 react만으로 코드를 짜본다.

    기본적으로 username, pw, email을 입력하는 input을 만들고, 각각 onChange함수를 만들어주고 submit을 하게 한다.

     

     

     

    //기본 form으로 짠 코드
    
    export default function Forms() {
      const [username, setUsername] = useState('');
      const [email, setEmail] = useState('');
      const [password, setPassword] = useState('');
      
      const onUsernameChanege = (e: React.SyntheticEvent<HTMLInputElement>) => {
        const {
          currentTarget: { value },
        } = e;
        setUsername(value);
      };
      const onEmailChange = (e: React.SyntheticEvent<HTMLInputElement>) => {
        const {
          currentTarget: { value },
        } = e;
        setEmail(value);
      };
      const onPasswordChange = (e: React.SyntheticEvent<HTMLInputElement>) => {
        const {
          currentTarget: { value },
        } = e;
        setPassword(value);
      };
      
      const onSubmit = (event: React.SyntheticEvent<HTMLFormElement>) => {
        event.preventDefault();
        console.log(password, email, username);
      };
      
      return (
        <form onSubmit={onSubmit}>
          <input
            value={username}
            onChange={onUsernameChanege}
            type="text"
            placeholder="Username"
            required
            minLength={5}
          />
          <input
            value={email}
            onChange={onEmailChange}
            type="email"
            placeholder="Email"
            required
          />
          <input
            value={password}
            onChange={onPasswordChange}
            type="password"
            placeholder="Password"
            required
          />
          <input type="submit" value="Create Account" />
        </form>
      );
    }

     

     

     

     

     

    추가적으로 유효성검사를 위한 코드를 고려해야하는데,

    const [formErrors, setFormErrors] = useState('');
    const [emailError, setEmailError] = useState('');
      
      const onSubmit = (event: React.SyntheticEvent<HTMLFormElement>) => {
        event.preventDefault();
        if (username === '' || email === '' || password === '') {
          setFormErrors('All fields are required');
        }
        if (!email.includes('@')) {
          setEmailError('~~');
        }
      };

     

     

    위의 코드에서는 input이 비어있을 경우와 email 입력시 @를 포함하지 않은 경우만 추가해 보았다.

    이외에도 비밀번호의 길이, 특수문자 추가 등 여러가지의 유효성검사를 하려면 수많은 state를 만들어야 하며,

    error후 수정이 되면 error msg를 사라지게 한다는 등의 form에 대한 user의 좋은 경험을 위해 고려해야할 사항들이 매우 많다.

    이러한 form코드를 좀 더 수월하게 짜기위하여 React hook form을 사용해보겠다.

     

     

     

     

     


     

     

     

     

     

    React Hook Form - useForm

     

     

     

    모든것은 useForm으로 구현이 된다.

    form에 기본 input을 만들고 useForm을 생성한다.

     

     

    import React, { useState } from 'react';
    import { useForm } from 'react-hook-form';
    
    export default function Forms() {
      const {} = useForm();
      return (
        <form>
          <input type="text" placeholder="Username" required minLength={5} />
          <input type="email" placeholder="Email" required />
          <input type="password" placeholder="Password" required />
          <input type="submit" value="Create Account" />
        </form>
      );
    }

     

     

     

    🔻 register

          :  input을 state에 연결한다.

             { ...register(inputName) }

          ( 기존에 state를 만들고, event listener를 등록하고, value를 input에 넣어주는 과정과 동일 )

    //동일한 역할 value={username},onChange={onChange}
    export default function Forms() {
    
      const { register } = useForm();
    
        <form>
          <input
            {...register('username')}   
            type="text"
            placeholder="Username"
            required
            minLength={5}
          ></input>

    console.log(register('name')

    register는 object를 반환하고, 그 안에는 name / onBlur / onChange / ref  4개가 있다.

    객체를 받아서 객체의 내부에 있는 속성들을 전부 가져다가 태그의 속성으로 넣어준다.

     

     

     

     

     

     

     

     

    🔻 watch

     : input값을 실시간으로 인식할 수 있다.

       ( event.target.value와 동일 )

     

    export default function Forms() {
      const {watch} = useForm
    
      console.log(watch('email'));

     

    console

     

     

     

    register로 현저히 줄어든 코드량

     

     

     

     

     

     


     

     

     

     

     

     

    🔻 Validation

     

     

     

    - input태그에 required를 넣었을 경우 user가 html에서 required를 삭제하고 올바르지않은 값을 보낼 수 있다.

      혹은, html required 속성(or 다른 속성들)을 지원하지 않는 브라우저일 수도 있다.

       → React hook form은 이러한 위험들을 방지할 수 있다.

     

     

     

    📌   지정하기를 원하는 속성을 register 다음에 객체로 넣어준다.

          <input
            {...(register('email'),
            {
              required: true,
            })}
            type="email"
            placeholder="Email"
          />

    사용할 수 있는 validation 규칙

    - min/max 숫자입력시 최소 최대 숫자 제한

    - min/maxLength 텍스트입력 길이 제한

    - pattern 정규식으로 입력값 필드 검증 시 사용 (이메일 등)

     

     

     

     

    📌   handleSubmit

        : event.PreventDefault 역할 (보다는 좀 더 강력)

          두 개의 인자를 받는 함수 ( onValid, onInvalid ), 1개는 필수

          → 첫번째는 form이 유효할 때만 실행되는 함수 onValid

               두번째는 유효하지 않을 때 실행되는 onInvalid

     

    export default function Forms() {
      // useForm에서 handleSubmit을 불러온다.
      const { register, handleSubmit } = useForm();
      
      // 유효성통과하면 console에 hi를 출력
      const onValid = () => {
        console.log('hi');
      };
    
      return (
       // 유효성검사에 통과하면 onvalid함수를 곧바로 실행한다
        <form onSubmit={handleSubmit(onValid)}>
        ...

     

     

     

     

     

    onInvalid

       : 유효성검사에 통과되지않을 시 error 메세지 전달하도록 지정

      const onInvalid = (errors: FieldErrors) => {
        console.log(errors);
      };
      
    
        // Form의 두번째 인자로 onInvalid
        <form onSubmit={handleSubmit(onValid, onInvalid)}>
          <input
            {...register('username', {
              required: 'Username is required',
              minLength: {
                //다섯글자 넘지 않을 시 알릴 메세지
                message: 'Username은 5자 이상으로 입력해야 합니다.',
                //최소 5자이상 입력
                value: 5,
              },
            })}
            type="text"
            placeholder="Username"
            required
            minLength={5}
          />

     

     

     

    username에 4글자 입력시 console에 type: 'minLength'

     

     

    5글자 입력하여 유효성 만족했을 시 username은 console에 뜨지않음!

     

     

     

     

     


     

     

     

     

     

     

     

     

    🔻 Errors

     

     

     

    📌   에러를 UI에 표시하기

     

    ex) gmail 사용제한

     

          <input
            {...register('email', {
              required: 'Email is required',
              validate: {
                notGmail: (value) =>
                  !value.includes('@gmail.com') || 'gmail은 사용하실 수 없습니다.',
              },
            })}
            type="email"
            placeholder="Email"
          />
          {errors.email?.message}

     

     

     

     

     

     

    📌 formState

     

       mode

         :  [ all, onBlur, onChange, onSubmit, onTouched ]

            onSubmit : 기본옵션, submit버튼 누르면 validation이 일어남

            onBlur : input의 바깥쪽을 클릭했을 때 발생

            onChange : input이 변할때마다 매번 validation (ex. ID가 사용중인지 입력시에 백엔드 fetch)

    export default function Forms() {
      const {
        formState: { errors },
      } = useForm<LoginForm>({
        mode: 'onBlur',
      });

     

     

     

     

     

    → Tailwind로 input의 state에 따라 에러 스타일 커스텀

          <input
            ...
          //email error메세지 발생 시 input border를 red로
            className={`${Boolean(errors.email?.message) ? 'border-red-100' : ''}`}
          />

     

     

     

     

     

    📌 setError

        setError('지정input', { message : '메세지내용'}

        { errors.지정input?.message }

     

    export default function Forms() {
      const {setError} = useForm<LoginForm>();
      
      const onValid = (data: LoginForm) => {
        setError('username', { message: '유저의 이름을 입력하세요.' });
      };
      
      return (
        <form onSubmit={handleSubmit(onValid, onInvalid)}>
          <input
            {...register('username', {
              required: 'Username is required',
              minLength: {
                message: 'Username은 5자 이상으로 입력해야 합니다.',
                value: 5,
              },
            })}
            type="text"
            placeholder="Username"
          />
          {errors.username?.message}

     

     

     

     

     

     

     

     

    📌 reset, resetField

       : reset은 전체 input을 reset, resetField는 지정한 input을 reset.

     

    export default function Forms() {
      const {
        reset,
        resetField,
      } = useForm<LoginForm>({
        mode: 'onChange',
      });
      
      const onValid = (data: LoginForm) => {
        reset();
        resetField('email');
      };

     

     

     

     

    🔻 참고사항

    더보기

    > Input을 컴포넌트로 만들어놓고 사용한다면

                <Input
                  register={register('email')}
                  name="email"
                  label="Email address"
                  type="email"
                  required
                />
    export default function Input({
      label,
      name,
      kind = 'text',
      register
      ...rest
    }: InputProps) {
      return (
      <input id={name} {...register} {...rest} />

     

     

     

     

     

     

     

     

    https://react-hook-form.com/

     

    Home

    React hook for form validation without the hassle

    react-hook-form.com

     

     

     
     
    반응형