(React) Formik & Yup

Mirrer·2022년 12월 22일
0

Library

목록 보기
15/17
post-thumbnail

React로 서비스를 개발하다보면 사용자 입력을 받아 처리하는 서식, 즉 Form 형태를 자주 접하게 된다.

아래는 대표적인 Form으로, 대부분 서비스에 존재하는 로그인 기능이다.

import React, { useCallback, useState } from 'react';

const LoginForm = () => {
  const [email, setEmail] = useState('');
  const [password, setPassword] = useState('');

  const onChangeEmail = useCallback(e => {
    setEmail(e.target.value);
  }, []);

  const onChangePassword = useCallback(e => {
    setPassword(e.target.value);
  }, []);

  const onSubmitForm = useCallback(
    e => {
      e.preventDefault();
      console.log(email, password);
    },
    [email, password],
  );

  return (
    <>
      <form onSubmit={onSubmitForm}>
        <label htmlFor="email">
          <div>EMAIL</div>
          <input type="email" id="email" name="email" value={email} onChange={onChangeEmail} />
        </label>

        <label htmlFor="password">
          <div>PASSWORD</div>
          <input type="password" id="password" name="password" value={password} onChange={onChangePassword} />
        </label>

        <button type="submit">LOGIN</button>
      </form>
    </>
  );
};

export default LoginForm;

Form은 작성하는 것은 물론 Form item별로 유효성검사와 같은 부가적인 기능을 추가하게 되면 체크 로직으로 인하여 코드가 매우 복잡해진다.

Formik, Yup은 이러한 단점을 해결하기 위해 사용되는 Form, 유효성 검사 라이브러리이다.


Formik

번거로운 Form 작업을 편리하게 해주는 라이브러리

React에서 Form을 관리하기 까다로운 만큼 이를 도와주는 라이브러리의 종류는 다양하다.

그 중 Formik는 다른 라이브러리들에 비해 성능이나 추론, 리펙토링...등등 많은 부분에서 우위를 점하고 있다.

Formik 공식문서에서는 Form 작업시 번거로운 3가지 작업을 언급하며, 이를 도와주는 라이브러리라고 설명되어 있다.

  • FormValue 가져오기

  • 유효성 검사 및 오류 메세지

  • Form Submit Handling


Yup

YupForm의 유효성 검사를 위한 라이브러리이며, 주로 Formik와 함께 React Form작업을 도와준다.

Yup은 아래 2가지 과정을 통해 Validation을 진행한다.

1. Yup Formatted Object를 생성 → 개발자가 의도한 스키마와 닮아있는 객체를 생성
2. Yup Utility Function을 통해 데이터 객체가 스키마와 매치되는지 확인


사용 방법

Package Install

아래 npm명령어를 통해 Formik, Yup 관련 패키지를 설치한다.

npm i formik
npm i yup

initialValues Setting

Form에서 사용 할 상태의 초기 값을 initialValues를 통해 설정한 뒤 value 속성으로 input과 연결한다.

  const formik = useFormik({
    initialValues: {
      email: '',
      password: '',
    },
  });
<label htmlFor="email">
  <div>EMAIL</div>
  <input type="text" id="email" name="email" value={formik.values.email} />
</label>

<label htmlFor="password">
  <div>PASSWORD</div>
  <input type="password" id="password" name="password" value={formik.values.password} />
</label>

handleChange 연결

input값이 변경 될 때 사용하는 onChangeformikhandleChange 속성을 통해 연결한다.

이 때 handleChange는 위에서 설정한 values[key] 값이 업데이트된다.

<label htmlFor="email">
  <div>EMAIL</div>
  <input 
    type="text" 
    id="email" 
    name="email" 
    value={formik.values.email} 
    onChange={formik.handleChange} 
  />
</label>

<label htmlFor="password">
  <div>PASSWORD</div>
  <input
    type="password"
    id="password"
    name="password"
    value={formik.values.password}
    onChange={formik.handleChange}
  />
</label>

onSubmit 연결

Form Submit 이벤트 리스너 연결은 <form>태그 onSubmit속성에 연결하며, handleSubmit속성을 사용한다.

또한 submit에 사용되는 함수도 초기값과 함께 작성한다.

<form onSubmit={formik.handleSubmit}>
  <label htmlFor="email">
    <div>EMAIL</div>
    <input 
      type="text" 
      id="email" 
      name="email" 
      value={formik.values.email} 
      onChange={formik.handleChange} 
    />
  </label>

  <label htmlFor="password">
    <div>PASSWORD</div>
    <input
      type="password"
      id="password"
      name="password"
      value={formik.values.password}
      onChange={formik.handleChange}
    />
  </label>

  <button type="submit">LOGIN</button>
</form>
 const formik = useFormik({
    initialValues: {
      email: '',
      password: '',
    },
    onSubmit: e => {
      console.log(e);
    },
  });

Validate

Formik Validate

입력한 값의 유효성 검사를 하기 위해 사용자 정의 유효성 검사 함수를 생성한 뒤 validateuseFormik hook에 연결한다.

이 때 useFomik에 전달한 onSubmit 함수는 오류가 없는 경우에만 실행된다.

 const validate = values => {
    const errors = {};
    const emailRule = /^[0-9a-zA-Z]([-_.]?[0-9a-zA-Z])*@[0-9a-zA-Z]([-_.]?[0-9a-zA-Z])*.[a-zA-Z]{2,3}$/i;

    if (!values.email) {
      errors.email = '이메일을 입력해주세요.';
    } else if (!emailRule.test(values.email)) {
      errors.email = '이메일 형식이 올바르지 않습니다.';
    }

    if (!values.password) {
      errors.password = '비밀번호를 입력해주세요.';
    }

    return errors;
  };

  const formik = useFormik({
    initialValues: {
      email: '',
      password: '',
    },
    onSubmit: e => {
      console.log(e);
    },
    validate,
  });

위의 코드를 실행해보면 첫 입력부터 에러를 발생시켜 좋지 않은 UX(User Experience)를 발생시킨다.

위와 같은 문제점을 해결하기 위해서는 touched 속성을 사용하여 사용자가 한 번이상 입력한 뒤에 유효성을 검사하도록 설정할 수 있다.

 <label htmlFor="email">
   <div>EMAIL</div>
   <input type="text" id="email" name="email" value={formik.values.email} onChange={formik.handleChange} />
 </label>
 {formik.touched.email && formik.errors.email && <div>{formik.errors.email}</div>}


Yup Validate

Yup을 사용한 유효성 검사는 기존 validate를 대신해 validationSchema를 사용한다.

아래 코드를 보면 확인할 수 있듯 Yup을 사용하면 Formik Validate
에 비해 코드의 양을 많이 줄일 수 있다.

const validationSchema = Yup.object({
  email: Yup.string().email('이메일 형식이 올바르지 않습니다.').required('Required'),
  password: Yup.string().max(10, '비밀번호는 최대 10글자입니다.').required('Required'),
});
const formik = useFormik({
  initialValues: {
    email: '',
    password: '',
  },
  onSubmit: e => {
    console.log(e);
  },
  validationSchema,
});


ETC...

getFieldProps

useFormikgetFieldProps를 사용하여 좀 더 빠른 적용을 지원한다.

<label htmlFor="email">
  <div>EMAIL</div>
  <input
    type="text"
    id="email"
    name="email"
    // value={formik.values.email}
    // onChange={formik.handleChange}
    {...formik.getFieldProps('email')}
  />
</label>
{formik.touched.email && formik.errors.email && <div>{formik.errors.email}</div>}

Formik 제공 컴포넌트

Formik기존 Form을 컨트롤하기 위해 아래와 같은 컴포넌트들을 제공한다.

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

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

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

<Formik initialValues={initialValues} validationSchema={validationSchema} onSubmit={onSubmit}>
  <Form>
    <label htmlFor="email">
      <div>EMAIL</div>
      <Field
        type="text"
        id="email"
        name="email"
        // className
        // as
      />
      <ErrorMessage name='name' component={<ErrorComponent />} />
    </label>
  </Form>
</Formik>

또한 component 속성에 커스텀 컴포넌트를 연결하면 아래와 같이 ErrorMessage 컴포넌트를 커스텀할 수 있다.

const ErrorComponent = props => <div {...props}></div>

oneOf

oneOfYup라이브러리 메서드로, 배열 입력값 중 하나를 선택할 때 사용할 수 있다.

nickname: Yup.string().oneOf(['user1', 'user2', 'user3']);

참고 자료

Formik: Build forms in React, without the tears
Yup - npm
React Formik Tutorial with Yup (React Form Validation)

profile
memories Of A front-end web developer

0개의 댓글