라이브러리

[Formik, Yup] Formik, Yup 사용하기

눙엉 2022. 4. 11. 01:00

front-end 하면 빠질 수 없는 것이 Form이다.

하나하나 만들어서 관리하려니 코드도 길어지고 너무 힘들어서 라이브러리를 통해 관리해보려고 찾아봤다.

 

대표적인 라이브러리로 Formik과 React-hook-form이 있다.

이번에는 form라이브러리인 Formik과 유효성 검사 라이브러리 Yup을 사용해보려 한다.

 

제일 처음 formik과 yup을 설치하자

npm i formik
npm i yup

 

 

form에 사용 할 상태의 초기 값을 initialValues을 통해서 설정한다.

  const formik = useFormik({
    initialValues: {
      firstName: "",
      lastName: "",
      channel: "",
    },
  });

 

초기 값을 사용 할 곳에서 value의 속성 값으로 초기 값을 연결해준다.

<label htmlFor="lastName">성</label>
<input
  type="text"
  id="lastName"
  name="lastName"
  value={formik.values.lastName} 
/>
<label htmlFor="lastName">이름</label>
<input
  type="text"
  id="firstName"
  name="firstName"
  value={formik.values.firstName} 
/>

 

input 값이 변경 될 때 사용하는 onChange에 formik의 handleChange를 연결한다.

여기서 handleChange를 사용하면 values [key]의 값이 업데이트된다. name 속성이 없으면 id 속성을 찾는다.

<label htmlFor="lastName">성</label>
<input
  type="text"
  id="lastName"
  name="lastName"
  value={formik.values.lastName} 
  onChange={formik.handleChange}
/>
<label htmlFor="lastName">이름</label>
<input
  type="text"
  id="firstName"
  name="firstName"
  value={formik.values.firstName} 
  onChange={formik.handleChange}
/>

 

폼 전송 이벤트 리스너 연결은 form태그의 onSubmit에 연결해준다.

    <form onSubmit={formik.handleSubmit}>
      <div>
        <label htmlFor="lastName">성</label>
        <input
          type="text"
          id="lastName"
          name="lastName"
          value={formik.values.lastName}
          onChange={formik.handleChange}
        />
      </div>
      <div>
        <label htmlFor="firstName">이름</label>
        <input
          type="text"
          id="firstName"
          name="firstName"
          value={formik.values.firstName}
          onChange={formik.handleChange}
        />
      </div>
      <button type="submit">전송</button>
    </form>

 

물론 submit에 사용하는 함수도 초기값과 함께 작성해준다.

  const formik = useFormik({
    initialValues: {
      firstName: "",
      lastName: "",
      channel: "",
    },
    onSubmit: (values) => {
      console.log(values);
    },
  });

 

입력한 값의 유효성 검사를 진행할 수 있다.

먼저 사용자 정의 유효성 검사 함수를 생성하고 validate로 useFormik() hook에 연결한다.

useFomik()에 전달한 onSubmit 함수는 오류가 없는 경우에만 실행된다. (유효성 검사 함수가 {}를 반환하는 경우)

const validate = (values) => {
  const errors = {};

  if (!values.firstName) {
    errors.name = "성 입력은 필수입니다.";
  } else if (values.firstName.length < 2) {
    errors.name = "성은 최대 2글자 입니다.";
  }

  if (!values.lastName) {
    errors.name = "이름 입력은 필수입니다.";
  }

  if (!values.email) {
    errors.email = "이메일 입력은 필수입니다.";
  } else if (!/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i.test(values.email)) {
    errors.email =
      "이메일 입력 형식이 올바르지 않습니다. 확인 후, 다시 입력하세요.";
  }

  return errors;
};

  const formik = useFormik({
    initialValues: {
      firstName: "",
      lastName: "",
      channel: "",
    },
    onSubmit: (values) => {
      console.log(values);
    },
    validate
  });

 

이제 연결한 validate를 조건에 따라 표시해보자

<label htmlFor="lastName">성</label>
<input
  type="text"
  id="lastName"
  name="lastName"
  value={formik.values.lastName}
  onChange={formik.handleChange}
/>
{formik.errors.lastName && <span role="alert">{formik.errors.lastName}</span>}

 

이제 콘솔창을 통해서 errors를 확인해보자

조건을 만족하지 못하면 errors [key] : value 값으로 객체에 생성될 것이고 모든 조건이 만족했다면 {} 빈객체를 반환할 것이다.

console.log(formik.errors)

 

validate를 이용하다보면 첫 입력부터 에러를 발생시킨다.

이러한 방법은 사용자에게 안좋은 경험을 만들어 주기 때문에 formik.touched를 사용해서 한 번이라도 입력한 후에 error를 발생시켜준다.

<label htmlFor="lastName">성</label>
<input
  type="text"
  id="lastName"
  name="lastName"
  value={formik.values.lastName}
  onChange={formik.handleChange}
/>
{formik.touched.lastName && formik.errors.lastName && <span role="alert">{formik.errors.lastName}</span>}

 

이제 Yup을 사용해서 유효성 검사를 해보자

import * as Yup from 'yup'

Yup의 validationSchema를 사용해서 유효성 검사를 진행하려 한다.

기존의 validate를 대신해 validationSchema를 사용하자.

const validationSchema = Yup.object({
   firstName: Yup.string()
     .max(2, '성은 최대 2글자 입니다.')
     .required('Required'),
   lastName: Yup.string()
     .required('Required'),
   email: Yup.string().email('이메일 입력 형식이 올바르지 않습니다. 확인 후, 다시 입력하세요.').required('Required'),
}),
const formik = useFormik({
  initialValues,
  validationSchema, //validate 삭제 후 입력
  onSubmit,
})

Formik 공식문서에서는 Yup 은 100% 옵션이라고 한다. 하지만 위에서 볼 수 있듯이 Yup을 사용하게 되면 코드를 많이 줄일 수 있다고 한다.

 

 

onChange -> handleChange, onBlur -> handleBlur등 이런 코드들은 Formik이 하는 일에 대해 매우 명시적이다.

useFormik()은 formik.getFieldProps()를 사용해서 더 빠르게 적용할 수 있도록 할 수 있다.

<label htmlFor="lastName">성</label>
<input
  type="text"
  id="lastName"
  name="lastName"
  //value={formik.values.lastName}
  //onChange={formik.handleChange}
  {...formik.getFieldProps('lastName')}
/>
{formik.touched.lastName && formik.errors.lastName && <span role="alert">{formik.errors.lastName}</span>}

 

이제 Formik 라이브러리가 제공하는 컴포넌트를 사용해서 폼을 컨트롤 해보자

import { Formik, Form, Field, ErrorMessage } from 'formik'

기본 적으로 Field는 input을 렌더링 한다. name props를 전달하면 암시적으로 각각의 onChange, onBlur, value props를 연결한다.

이 외의 as, className props들도 사용 가능하다.

<Formik
  initialValues={initialValues}
  validationSchema={validationSchema}
  onSubmit={onSubmit}
>
  <Form>
      <label htmlFor="firstName">이름</label>
      <Field
        type="text"
        id="firstName"
        name="firstName"
        //className
        //as
      />
     <ErrorMessage name="name" component={ErrorMessageComponent} />
  </Form>
</Formik>

여기서 사용한 ErrorMessage 컴포넌트를 커스텀하기 위해 component 속성에 커스텀 컴포넌트를 연결한다.

const ErrorMessageComponent = (props) => <span role="alert" {...props} />

 

Yup 메서드

 

oneOf

language: Yup.string().oneOf(['javascript', 'c', 'c++', 'java']) // 배열에 입력한 항목 중 하나를 선택 해야 할 때 사용한다.

 

 

'라이브러리' 카테고리의 다른 글

react-helmet  (0) 2021.09.12