ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • react에서 회원가입 form입력받기 (react-hook-form + yup)
    React 2022. 5. 29. 22:23

    개인 프로젝트를 할때든, 실제 앱/웹 서비스를 만들든 꼭 처음에 만들게 되는 화면이있다.

    바로 로그인/회원가입 화면!

     

    물론 요즘에는 소셜 로그인이 생기면서 입력할게 점점 줄어들고 있긴 하지만,

    아직 이메일로 회원가입 하는 창도 있어야하는건 마찬가지다.

     

    useState Hook 사용하기

    보통 처음에 react에 입문할때는 useState hook 을 이용해서 입력값을 받아오는 법을 배운다.

    function App() {
      const [email, setEmail] = useState('');
      const [password, setPassword] = useState('');
    
      const handleSubmit = (e) => {
        e.preventDefault();
        console.log(`submit! ${email} ${password}`);
      };
    
      return (
        <div className="App">
          <h1>React Input Test!</h1>
          <form onSubmit={handleSubmit}>
            <input
              name="email"
              value={email}
              placeholder="이메일"
              onChange={(e) => setEmail(e.target.value)}
            />
            <input
              type="password"
              name="password"
              value={password}
              placeholder="비밀번호"
              onChange={(e) => setPassword(e.target.value)}
            />
            <input type="submit" />
          </form>
        </div>
      );
    }

    대략 짜보면 위와 같다.

     

    하지만 받아야할 input이 많다면 여러가지 고민해야할 것이 많아진다.

    input을 이메일, 비밀번호, 비밀번호 확인 창까지 3개로 늘려보았다.

    아무래도 비밀번호 확인 창이 있으니 입력한 비밀번호가 맞는지 틀린지도 확인하는 코드가 필요할 것 같다.

     

    function App() {
      const [email, setEmail] = useState('');
      const [password, setPassword] = useState('');
      const [passwordConfirm, setPasswordConfirm] = useState('');
    
      const handleSubmit = (e) => {
        e.preventDefault();
        console.log(`submit! ${email} ${password} ${passwordConfirm}`);
      };
    
      return (
        <div className="App">
          <h1>React Input Test!</h1>
          <form onSubmit={handleSubmit}>
            <input
              name="email"
              value={email}
              placeholder="이메일"
              onChange={(e) => setEmail(e.target.value)}
            />
            <input
              type="password"
              name="password"
              value={password}
              placeholder="비밀번호"
              onChange={(e) => setPassword(e.target.value)}
            />
            <input
              type="password"
              name="passwordConfirm"
              value={passwordConfirm}
              placeholder="비밀번호 확인"
              onChange={(e) => setPasswordConfirm(e.target.value)}
            />
            {password !== passwordConfirm && <p>비밀번호가 일치하지 않습니다.</p>}
            <input type="submit" />
          </form>
        </div>
      );
    }

    하지만 보통 회원가입창에서 입력하는 내용들엔 서비스에 따라 규칙이 있다. 예를 들어, 이메일은 이메일 형식이어야하고, 비밀번호는 영어와 숫자의 조합이어야한다. 이를 위해선 input의 onChange에 각각 검증하는 로직을 넣어줘야한다.

    이제 여기에 핸드폰 번호가 추가되고, 닉네임도 입력을 받는다고 해보자. 그렇게 되면 과연 이 모든것을 state로 관리하는게 좋은것인지 의문이 생긴다.

     

    이번에 팀원분이 이런 입력을 받는 화면에서 사용할 수 있는 react-hook-form + yup 조합을 알려주셨는데 너무 편하게 코드를 짤 수 있었다. 

     

    react-hook-form과 yup은 둘다 가이드라인이 친절한 편이라 쉽게 사용할 수 있다.

     

    React Hook Form 라이브러리 사용하기

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

     

    Home

    React hook for form validation without the hassle

    react-hook-form.com

     

    일단 라이브러리를 추가하고

    npm install react-hook-form

     

    기존에 사용하던 state 관련 내용을 전부 지우고 input 에 register를 넣어주면 된다. 그리고 handleSubmit을 통해 input에 넣은 데이터값을 받아올 수 있다.

     

    import { useForm } from 'react-hook-form';
    
    function App() {
      const {
        register,
        handleSubmit,
      } = useForm();
      const onSubmit = (data) => console.log(data);
    
      return (
        <div className="App">
          <h1>React Input Test!</h1>
          <form onSubmit={handleSubmit(onSubmit)}>
            <input name="email" placeholder="이메일" {...register('email')} />
            <input
              type="password"
              name="password"
              placeholder="비밀번호"
              {...register('password')}
            />
            <input
              type="password"
              name="passwordConfirm"
              placeholder="비밀번호 확인"
              {...register('passwordConfirm')}
            />
            <input type="submit" />
          </form>
        </div>
      );
    }

     

     

    react-hook-form을 사용하면, 각 input이 변화할때마다 불필요한 리랜더링을 방지할 수 있을뿐만 아니라 다양한 검증 기능 또한 사용할 수 있다. 각 필드에 error message 가 존재할 경우 그 에러 메시지를 보여줄 수 있다.

     

    function App() {
      const {
        register,
        handleSubmit,
        formState: { errors },
      } = useForm();
      const onSubmit = (data) => console.log(data);
    
      return (
        <div className="App">
          <h1>React Input Test!</h1>
          <form onSubmit={handleSubmit(onSubmit)}>
            <input
              name="email"
              placeholder="이메일"
              {...register('email', { required: '이메일을 입력해주세요' })}
            />
            {errors.email && <p>{errors.email.message}</p>}
            <input
              type="password"
              name="password"
              placeholder="비밀번호"
              {...register('password', {
                required: '비밀번호를 입력해주세요',
                minLength: {
                  value: 6,
                  message: '최소 6자 이상의 비밀번호를 입력해주세요',
                },
              })}
            />
            {errors.password && <p>{errors.password.message}</p>}
            <input
              type="password"
              name="passwordConfirm"
              placeholder="비밀번호 확인"
              {...register('passwordConfirm')}
            />
            <input type="submit" />
          </form>
        </div>
      );
    }

     

     

    Yup 라이브러리 사용하기

    https://github.com/jquense/yup

     

    GitHub - jquense/yup: Dead simple Object schema validation

    Dead simple Object schema validation. Contribute to jquense/yup development by creating an account on GitHub.

    github.com

    여기에 yup을 사용하면 좀 더 편하게 검증로직을 넣을 수 있다.

     

    npm install yup
    npm install @hookform/resolvers

     

    yup.object를 통해 schema를 만들어서 검증로직 및 에러메시지를 한번에 정의해줄 수 있다. 또한 email()이나 oneOf() 등 제공해주는 다양한 API를 사용할 수 있다.

    import { useForm } from 'react-hook-form';
    import { yupResolver } from '@hookform/resolvers/yup';
    import * as yup from 'yup';
    
    function App() {
      const formSchema = yup.object({
        email: yup
          .string()
          .required('이메일을 입력해주세요')
          .email('이메일 형식이 아닙니다.'),
        password: yup
          .string()
          .required('영문, 숫자포함 8자리를 입력해주세요.')
          .min(8, '최소 8자 이상 가능합니다')
          .max(15, '최대 15자 까지만 가능합니다')
          .matches(
            /^(?=.*[A-Za-z])(?=.*\d)[A-Za-z\d]{8,15}$/,
            '영문 숫자포함 8자리를 입력해주세요.'
          ),
        passwordConfirm: yup
          .string()
          .oneOf([yup.ref('password')], '비밀번호가 다릅니다.'),
      });
    
      const {
        register,
        handleSubmit,
        watch,
        formState: { errors },
      } = useForm({
        mode: 'onChange',
        resolver: yupResolver(formSchema),
      });
    
      const onSubmit = (data) => console.log(data);
    
      return (
        <div className="App">
          <h1>React Input Test!</h1>
          <form onSubmit={handleSubmit(onSubmit)}>
            <input name="email" placeholder="이메일" {...register('email')} />
            {errors.email && <p>{errors.email.message}</p>}
            <input
              type="password"
              name="password"
              placeholder="비밀번호"
              {...register('password')}
            />
            {errors.password && <p>{errors.password.message}</p>}
            <input
              type="password"
              name="passwordConfirm"
              placeholder="비밀번호 확인"
              {...register('passwordConfirm')}
            />
            {errors.passwordConfirm && <p>{errors.passwordConfirm.message}</p>}
            <input type="submit" disabled={errors || watch()} />
          </form>
        </div>
      );
    }

     

     

    응용할 수 있는 방법이 매우 많아서, 필요에 따라 라이브러리 문서를 보며 적용하면 좋을 것 같다.

    댓글

Designed by Tistory.