Formik & Yup

임지선·2023년 11월 6일
1
post-thumbnail

formik 이란?

form 라이브러리로, Formik 공식문서 에서는 Formik이 가지는 장점을 아래와 같이 설명합니다.

  • Getting values in and out of form state: 값 상태 관리
  • Validation and error messages: 유효성 검사
  • Handling form submission: 제출 방식 제어
  • Formik은 단순히 input component 관리를 넘어서서 데이터의 흐름을 제어할 수 있는데 효과적이라고 표현합니다.
    Formik을 사용하면 마치 Context API를 사용하는 것처럼 form이 필요한 컴포넌트를 태그로 감싸주어 props drilling 없이 '컴포넌트 내에서 전역적으로 상태 관리'를 할 수 있습니다.
    또한 form에서 늘 빠질 수 없는 유효성 검사까지 같이 해줄 수 있다는 장점이 있습니다.

formik 과 react hook form 차이점

  • 코드 라인 및 글자 수
    코드 라인은 formik이 더 적으며, 코드 글자 수는 react hook form 이 더 적습니다.(전체적으로 formik이 코드를 더 간결하게, 직관적으로 짤 수 있음)
  • 생태계 비교
    image
    react hook form이 가장 우수하며, 그 뒤를 formik이 따르고 있습니다.
    2022년도까지는 formik이 더 선호도가 높았다면 2023년도에 이르러 react hook form이 더 높아졌습니다.
  • 번들 크기 비교
    image
    react-hook-form이 가장 작은 것을 확인할 수 있으며, 그 다음으로 formik이 잇따릅니다.
  • 종속성 비교
    image
    react hook form은 종속성이 없으며, formik은 약 7~8개 정도의 종속성을 지닙니다.
  • 실행 속도
    performance 측면이나 network 측면에서 모두 react hook form이 우수하나 이는 상대적으로 비교했을 때 가장 빠른 것일 뿐 그 외의 formik이나 rc-field-form과 같은 다른 form 라이브러리도 우수합니다.
  • 리렌더링 비교
    압도적으로 react hook form 이 리렌더링 횟수가 적은 편입니다.
    image

요약

생태계 측면에서, 생태계의 크기에서 react-hook-form, formik 이 2가지 중 선택할 수 있습니다.
사용성 측면에서, formik에서 제공하는 컴포넌트를 사용할 경우 코드 양을 줄일 수 있습니다.
성능 측면에서, react-hook-form은 번들 크기가 작아 첫 렌더링 속도가 빠르고, 리렌더링 횟수가 월등히 적기 때문에 성능 측면으로 본다면 react-hook-form이 더 좋습니다.
유연성 측면에서, react-hook-form은 Uncontrolled 방식으로 성능이 뛰어나지만, 폼 값을 컨트롤하기 어렵습니다. 이 단점을 보완하기 위해 watch라는 기능이 존재하지만, formik는 Controlled 방식이기 때문에 폼 값을 좀 더 유연성 있게 다룰 수 있어 유연성 측면에서는 formik가 더 좋습니다.(watch를 사용해 react hook form을 controlled 처럼 이용할 수 있으나 controlled를 지향하는 react에서 추천하는 방식은 아닙니다.)

Formik은 리액트가 권장하는 Controlled Component를 만드는 것에 힘썼다면, React-Hook-Form은 퍼포먼스 최적화에 힘을 실었다고 할 수 있습니다.

formik 장단점 정리

  • 장점
    폼 값을 유연성있게 다룰 수 있으며, state 방식과 context 방식이기 때문에 직관적이고 쉽게 데이터 흐름을 제어할 수 있습니다. 추가적으로 controlled component 방식이기 때문에 context api처럼 데이터를 다룰 수 있어 하나의 컴포넌트로 여러 곳에서 입력받은 데이터들을 부모 컴포넌트에서() 전역으로 관리할 수 있습니다.
    코드를 간결하게 구현할 수 있으며, validation 처리하는 데 있어 매우 편리한 기능을 제공합니다.(error, validate, 등)
  • 단점
    react hook form 보다는 성능 측면에서 떨어집니다.(그 외에는 큰 차이가 없으나 리렌더링에서는 차이가 확실함)
    부분적인 watch 처리가 불가능합니다.(부분적으로 렌더링할 대상 결정 불가능)

formik 사용 방법 예제 정리

formik 사용 방법

먼저, 컴포넌트가 가장 외곽이 됩니다. 이는, initialValues, onSubmit 2가지 Props를 기본적으로 요구받습니다.

<< Formik Props >>
굵은 글씨만 참고해주셔도 괜찮습니다.

  • initialValues : 폼 내에서 쓸 데이터의 기본값. 객체를 받으며, 각 key는 내부 input의 name과 대응된다.
  • onSubmit : 폼에서 Submit 이벤트가 발생했을 때 실행할 핸들러 함수를 등록한다.
    인자는 values(입력값 객체), actions(폼의 에러상태, 제출중인 상태(submitting), 폼 리셋 등의 추가조작) 2가지를 받는다.
  • 이외에도, validate(유효성 검사 함수), validatoinSchema(유효성 검사 객체) 등 인자를 받는다.(yup을 사용해 schema로 처리하면 더 간단하게 처리 가능)

<< Render Props >>

  • values : <input> 등의 각 name과 이에 해당하는 value들의 값을 저장하는 객체. 각 name을 key로 값을 조회 가능하며, 위의initialValutes로 초기화.
  • errors : validate 함수로 반환한 에러 정보를 저장하는 객체. 각 name을 key로 에러 메세지 조회 가능 (메세지가 있으면 에러)
  • handleSubmit : 위의 onSubmit에 등록한 핸들러 함수. <form>의 onSubmit 이벤트 핸들러로 등록
  • handleChange : 내부 엘리먼트의 값 변경을 연동하는 핸들러 함수. <input> 등의 onChange 이벤트 핸들러로 등록
  • handleBlur : 내부 엘리먼트의 focusOut 동작과 연동하는 핸들러 함수(에러 핸들링). <input> 등의 onBlur 이벤트 핸들러로 등록
  • touched : 사용자가 내부 엘리먼트와 인터렉션이 있었는지 여부를 저장하는 객체. 각 name을 key로 확인
  • isSubmitting : 위의 onSubmit 핸들러로 설정한 setSubmitting의 true/false 여부. 비동기 통신중임을 표현하기 위해 활용
  • 이외에도, dirty(initialValues와 깊은복사 일치 여부), isValid(유효성 여부), 및 value, error, 각 필드에 대한 제어 메서드 등이 존재

formik 사용 예제

const initialValues = { // values의 초기값을 설정해주세요.(폼을 통해 입력받을 값들 초기값)
    storeNumber: '',
    name: 0,
    name: false, // 이런 식으로 name 자리에 변수명을 작성해주시고, 초기값을 넣어주면 됩니다.
  };
  const schema = object().shape({ // yup을 이용한 validation 
      storeNumber: string() // name 자리에 validation할 변수명을 넣어주고, 그 변수의 타입을 지정해주세요. 예시로 string(), number(), object() 등이 있습니다.
      .required(ERROR_MESSAGE.STORE_REQUIRED) // 하단 yup 정리 내용 참고
      .matches(/^[0-9]+$/, ERROR_MESSAGE.STORE_NUMBER)
      .length(10, ERROR_MESSAGE.STORE_LENGTH),
  });

  const submitForm = (values: initialValuesType) => { // 폼을 제출할 때 실행되는 헨들러 내용을 함수로 만들어주세요. 만든 함수는 onSubmit에 넣어주세요.
    console.log(values)
  };

return (<Formik // Formik으로 폼 감싸주기
        initialValues={initialValues} // 폼으로 입력받은 값들 초기값 설정
        validationSchema={schema} // 각 변수마다 validation할 조건들 설정
        onSubmit={submitForm} // 폼 제출시 실행할 헨들러 설정
      >
        {formik => { // formik을 props로 전달
          return (
            <Form> // 자유롭게 Form 작성
              <label className="text-xs font-semibold" htmlFor="storeNumber">
                사업자 등록번호
              </label>
              <Field // 이때 input 대신 Field 사용, input과 동일하게 사용하며, onChange등은 줄 필요가 없고 필수로 type과 name은 지정해주셔야 합니다.
                type="text"
                name="storeNumber" // 이때 name이 곧 각 입력값을 구분하는 변수명이자 아이디가 되므로 초기값 설정한 name과 동일하게 지정해주세요.
                className={`h-12 w-full rounded ${
                  formik.errors.storeNumber ? 'border-red' : 'border-yellow'
                } bg-white pl-3 outline-none focus:border-2`}
                placeholder="1007999997"
              />
              <ErrorMessage // formik에서 제공하는 ErrorMessage를 사용하면 자동으로 validation을 확인해 error일 경우 표시됩니다. (error && <div>에러 메시지</div> 할 필요 x)
                name="storeNumber" // 이때 또한 해당 변수명을 name으로 일치시켜야 합니다.
                component="span" // 에러 메시지는 어떤 형태로 보여줄 지 설정할 수 있습니다. p태그, span태그, div태그 등 다양하게 가능합니다.
                className="w-full text-left text-xs text-red"
              />
              <PrimaryButton type="submit">다음</PrimaryButton> // 버튼 onClick 설정없이 type을 submit으로 설정해주세요.
            </Form>
          );
        }}
      </Formik> )

이 외에 좀 더 자세한 내용이나 다른 예제들을 참고하고 싶다면 아래 참고 자료에서 formik 공식 문서와 formik 예제를 참고해주세요.

yup 라이브러리 소개

Yup은 JavaScript에서 사용되는 객체 스키마 유효성 검사 라이브러리입니다. 이를 통해 간편하게 데이터의 유효성을 확인하고 검증할 수 있습니다.

yup 사용 방법 예제 정리

// 에러 메시지 자리에 이 validation을 어겼을 때 띄울 에러 메시지를 넣어주기

//string()
.required(에러 메시지) // 필수 입력란
.matches(보통 정규표현식, 에러 메시지) // 입력 양식 지정
.length(길이, 에러 메시지), // string일 경우 문자열 길이 지정
.min(조건, 에러 메시지) // 최소 문자열 길이 지정
.max(조건, 에러 메시지) // 최대 문자열 길이 지정

//number()
.required(에러 메시지) // 필수 입력란
.positive(에러 메시지) // 보통 변수 타입이 number()라면 양수인지 확인
.negative(에러 메시지) // 음수인지 확인
.integer(에러 메시지) // 정수인지 확인

//array()
.required(에러 메시지) // 필수 입력란
.length(길이, 에러 메시지), // 배열 길이 지정
.min(조건, 에러 메시지) // 최소 배열 길이 지정
.max(조건, 에러 메시지) // 최대 배열 길이 지정

그 외의 조건들은 하단의 yub schema 예제 참고 블로그와 yup 제공 기능 종류를 참고해주세요.

참고자료

npm trend 다운로드 그래프
react hook form vs formik

formik 공식 문서
formik 예제
formik 사용방법 설명 블로그

yup npm 공식 문서
yup schema 예제 참고 블로그
yup 제공 기능 종류

profile
성장하는 프론트엔드 개발자입니다.

0개의 댓글