formik + yup 사용해보기 -2

드엔트론프·2022년 11월 18일
0
post-thumbnail

이제 유효성 검사를 추가한 formik을 살펴보자.
yup을 쓰는건 아니고, 먼저 기본적으로 if 문을 사용하여 유효성 검사를 하는 형태다.

유효성검사

import React from 'react';
 import { useFormik } from 'formik';
 
 // 커스텀한 유효성검사 함수. 얘네는 반드시 우리의 값/초깃값에 대칭되는 객체를 반환한다.
 const validate = values => {
   const errors = {};
   if (!values.firstName) {
     errors.firstName = 'Required';
   } else if (values.firstName.length > 15) {
     errors.firstName = 'Must be 15 characters or less';
   }
 
   if (!values.lastName) {
     errors.lastName = 'Required';
   } else if (values.lastName.length > 20) {
     errors.lastName = 'Must be 20 characters or less';
   }
 
   if (!values.email) {
     errors.email = 'Required';
   } else if (!/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i.test(values.email)) {
     errors.email = 'Invalid email address';
   }
 
   return errors;
 };
 
 const SignupForm = () => {
   const formik = useFormik({
     initialValues: {
       firstName: '',
       lastName: '',
       email: '',
     },
     validate,
     onSubmit: values => {
       alert(JSON.stringify(values, null, 2));
     },
   });
   return (
     <form onSubmit={formik.handleSubmit}>
       <label htmlFor="firstName">First Name</label>
       <input
         id="firstName"
         name="firstName"
         type="text"
         onChange={formik.handleChange}
         value={formik.values.firstName}
       />
       {formik.errors.firstName ? <div>{formik.errors.firstName}</div> : null}
 
       <label htmlFor="lastName">Last Name</label>
       <input
         id="lastName"
         name="lastName"
         type="text"
         onChange={formik.handleChange}
         value={formik.values.lastName}
       />
       {formik.errors.lastName ? <div>{formik.errors.lastName}</div> : null}
 
       <label htmlFor="email">Email Address</label>
       <input
         id="email"
         name="email"
         type="email"
         onChange={formik.handleChange}
         value={formik.values.email}
       />
       {formik.errors.email ? <div>{formik.errors.email}</div> : null}
 
       <button type="submit">Submit</button>
     </form>
   );
 };

커스텀한 유효성검사 함수 validate를 만들고, 그 안에 initialValue 중 유효성 검사가 필요한 애들을 조건문으로 정의한다.
useformik 에서 initialValues 다음 validate를 부른다.
이제 input 값을 작성하고 다음 input을 작성할 때 조건이 맞지 않는다면 에러가 뜬다.
이때 onSubmit은 당연하게도 에러가 없어야 실행이 된다.
(영상은 css가 하나도 없어서 구리네)

근데 아쉬운점은 하나의 인풋값을 작성하는 순간 모든 유효성검사의 친구들이 반응한다는 점이다.
뭔가 아쉽다!

계속 나아가보자.

Field 방문하기

위에 아쉬운점에 언급했듯, 보통 우리는 인풋값을 작성했을 때 값이 유효한지에 대해 해당 인풋값만 에러메세지를 뱉길 원한다. 그렇게 만들어보자.

formik은 에러나 값에 관련해서 계속해서 추척한다. 이 정보를 touched라는 객체에 저장한다.
touched : touch 객체이며, values/initialValues의 모양도 미러링하는 저장된다. touch의 키는 필드 이름이고, touch의 값은 참/거짓 이다. 터치를 활용하기 위해 formik.handleBlur를 각 입력의 onBlur prop에 전달한다. 이 함수는 이름 속성을 사용하여 업데이트할 필드를 파악한다는 점에서 formik.handleChange와 유사하게 작동한다.

  • onblur event 란
    • 인풋 창 포커스했다가 떨어졌을 때 보여지는 이벤트이다. 이렇게 유효성 검사할 때 많이 쓰인다고 한다.
      onblur Event

 import { useFormik } from 'formik';
 
 const validate = values => {
   const errors = {};
   if (!values.firstName) {
     errors.firstName = 'Required';
   } else if (values.firstName.length > 15) {
     errors.firstName = 'Must be 15 characters or less';
   }
 
   if (!values.lastName) {
     errors.lastName = 'Required';
   } else if (values.lastName.length > 20) {
     errors.lastName = 'Must be 20 characters or less';
   }
 
   if (!values.email) {
     errors.email = 'Required';
   } else if (!/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i.test(values.email)) {
     errors.email = 'Invalid email address';
   }
 
   return errors;
 };
 
 const SignupForm = () => {
   const formik = useFormik({
     initialValues: {
       firstName: '',
       lastName: '',
       email: '',
     },
     validate,
     onSubmit: values => {
       alert(JSON.stringify(values, null, 2));
     },
   });
   return (
     <form onSubmit={formik.handleSubmit}>
       <label htmlFor="firstName">First Name</label>
       <input
         id="firstName"
         name="firstName"
         type="text"
         onChange={formik.handleChange}
		//추가된 부분
         onBlur={formik.handleBlur}
         value={formik.values.firstName}
       />
       {formik.errors.firstName ? <div>{formik.errors.firstName}</div> : null}
 
       <label htmlFor="lastName">Last Name</label>
       <input
         id="lastName"
         name="lastName"
         type="text"
         onChange={formik.handleChange}
		//추가된 부분
         onBlur={formik.handleBlur}
         value={formik.values.lastName}
       />
       {formik.errors.lastName ? <div>{formik.errors.lastName}</div> : null}
 
       <label htmlFor="email">Email Address</label>
       <input
         id="email"
         name="email"
         type="email"
         onChange={formik.handleChange}
		//추가된 부분
         onBlur={formik.handleBlur}
         value={formik.values.email}
       />
       {formik.errors.email ? <div>{formik.errors.email}</div> : null}
 
       <button type="submit">Submit</button>
     </form>
   );
 };

추가된 부분

onBlur={formik.handleBlur}

별거 없다. 기존 거에서 해당 부분만 추가되어있다.
딱 여기까지만 쓰면 하나만 입력해도 모든 유효성검사가 튀어나오는 맨 처음 작성한 것과 다를바 없다.
여기서 에러 메세지를 touched로 검사하는 한 줄이 더 추가되어야 한다.

import React from 'react';
 import { useFormik } from 'formik';
 
 const validate = values => {
   const errors = {};
 
   if (!values.firstName) {
     errors.firstName = 'Required';
   } else if (values.firstName.length > 15) {
     errors.firstName = 'Must be 15 characters or less';
   }
 
   if (!values.lastName) {
     errors.lastName = 'Required';
   } else if (values.lastName.length > 20) {
     errors.lastName = 'Must be 20 characters or less';
   }
 
   if (!values.email) {
     errors.email = 'Required';
   } else if (!/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i.test(values.email)) {
     errors.email = 'Invalid email address';
   }
 
   return errors;
 };
 
 const SignupForm = () => {
   const formik = useFormik({
     initialValues: {
       firstName: '',
       lastName: '',
       email: '',
     },
     validate,
     onSubmit: values => {
       alert(JSON.stringify(values, null, 2));
     },
   });
   return (
     <form onSubmit={formik.handleSubmit}>
       <label htmlFor="firstName">First Name</label>
       <input
         id="firstName"
         name="firstName"
         type="text"
         onChange={formik.handleChange}
         onBlur={formik.handleBlur}
         value={formik.values.firstName}
       />
        //추가된부분
       {formik.touched.firstName && formik.errors.firstName ? (
         <div>{formik.errors.firstName}</div>
       ) : null}
 
       <label htmlFor="lastName">Last Name</label>
       <input
         id="lastName"
         name="lastName"
         type="text"
         onChange={formik.handleChange}
         onBlur={formik.handleBlur}
         value={formik.values.lastName}
       />
        //추가된부분
       {formik.touched.lastName && formik.errors.lastName ? (
         <div>{formik.errors.lastName}</div>
       ) : null}
 
       <label htmlFor="email">Email Address</label>
       <input
         id="email"
         name="email"
         type="email"
         onChange={formik.handleChange}
         onBlur={formik.handleBlur}
         value={formik.values.email}
       />
       //추가된부분
       {formik.touched.email && formik.errors.email ? (
         <div>{formik.errors.email}</div>
       ) : null}
 
       <button type="submit">Submit</button>
     </form>
   );
 };

이제는 개별 인풋값마다 반응하는 걸 볼 수 있다 !
다음 편에선 대망의 yup을 사용하여 유효성 검사하는 편을 작성해보려한다.

이렇게 끊어서 차근차근 보면 좀 더 이해되는 것 같다.

profile
왜? 를 깊게 고민하고 해결하는 사람이 되고 싶은 개발자

0개의 댓글