[FDBS] react-hook-form vs formik vs redux-form

Jay ·2023년 7월 23일
0

직접 구현?

Form 관련 라이브러리를 사용하는 이유

직접 로직을 구현하기에는 validation,form fields, error 등 고려해야할 부분이 너무 많고, 직접 작성할 경우 코드가 과도하게 늘어난다.

또한, state에 기반해 form을 구성(제어 컴포넌트로)할 경우, 불필요한 렌더링이 과도하게 발생할 수 있다.

물론 colocation과 Ref를 활용해 이를 직접 구현할 수도 있지만, 이를 직접 구현하기에는 데이터가 여러군데로 분산되어 유지 및 관리의 난이도가 너무 높아지고 굳이 기존 라이브러리를 사용하지 않을 이유가 없기 때문에 기존 라이브러리를 도입하기로 하였다.

라이브러리 비교

FeaturesReact Hook FormFormikRedux Form
Componentuncontrolled & controlledcontrolledcontrolled
Renderingminimum re-renderre-render according to local state changes which means as you type in the input.re-render according to state management lib (Redux) changes which means as you type in the input.
APIHooksComponent (RenderProps, Form, Field) + HooksComponent (RenderProps, Form, Field)
Package sizeSmall react-hook-form@7.0.0 8KBMedium formik@2.1.4 15KBLarge redux-form@8.3.6 26.4KB
ValidationBuilt-in, Yup, Zod, Joi, Superstruct and build your own.Build yourself or YupBuild yourself or Plugins
Learning curveLow to MediumMediumMedium
No. of mountsOnly requires mounting the formIt mounts the form, some additional components, and uses a special component for fieldsIt mounts the form, some additional components, and uses a special component for fields
No. of committing changes1617
Total mounting times1800ms2070ms2380ms

성능면에서 react-hook-form이 가장 뛰어나다.
또한 비제어 방식으로 form을 관리할 수 있다는 장점이 있는 React-hook-form을 사용하기로 하였다.

React-hook-form 적용 과정

Example


import { useForm } from "react-hook-form";

export default function App() {
  const { register, handleSubmit, watch, formState: { errors } } = useForm();
  const onSubmit = data => console.log(data);

  console.log(watch("example")); // watch input value by passing the name of it

  return (
    /* "handleSubmit" will validate your inputs before invoking "onSubmit" */
    <form onSubmit={handleSubmit(onSubmit)}>
      {/* register your input into the hook by invoking the "register" function */}
      <input defaultValue="test" {...register("example")} />
      
      {/* include validation with required or other standard HTML validation rules */}
      <input {...register("exampleRequired", { required: true })} />
      {/* errors will return when field validation fails  */}
      {errors.exampleRequired && <span>This field is required</span>}
      
      <input type="submit" />
    </form>
  );
}

Register

Register를 사용하면 5줄의 코드를 다음과 같이 줄일 수 있다.

const { onChange, onBlur, name, ref } = register('firstName'); 
// include type check against field path with the name you have supplied.
        
<input 
  onChange={onChange} // assign onChange event 
  onBlur={onBlur} // assign onBlur event
  name={name} // assign name prop
  ref={ref} // assign ref prop
/>
// same as above
<input {...register('firstName')} />

UseFieldArray

function FieldArray() {
  const { control, register } = useForm();
  const { fields, append, prepend, remove, swap, move, insert } = useFieldArray({
    control, // control props comes from useForm (optional: if you are using FormContext)
    name: "test", // unique name for your Field Array
  });

  return (
    {fields.map((field, index) => (
      <input
        key={field.id} // important to include key with field's id
        {...register(`test.${index}.value`)} 
      />
    ))}
  );
}

Validation

다음과 같이 간편하게 regex 등을 활용한 검증이 가능하다.

<input name="firstName" 
  ref={register({ required: true, maxLength: 20 })} />
<input name="lastName" 
  ref={register({ pattern: /^[A-Za-z]+$/i })} />
<input name="age" type="number" 
  ref={register({ min: 18, max: 99 })} />

UseFormContext

중첩된 컴포넌트 구조에서 Provider를 통해 context형식으로 method를 넘겨줄 수 있다.

import React from "react"
import { useForm, FormProvider, useFormContext } from "react-hook-form"

export default function App() {
  const methods = useForm()
  const onSubmit = (data) => console.log(data)

  return (
    <FormProvider {...methods}>
      // pass all methods into the context
      <form onSubmit={methods.handleSubmit(onSubmit)}>
        <NestedInput />
        <input type="submit" />
      </form>
    </FormProvider>
  )
}

function NestedInput() {
  const { register } = useFormContext() // retrieve all hook methods
  return <input {...register("test")} />
}

Devtool

react-hook-form은 dev tool을 제공한다.
form의 데이터 변화를 콘솔에 찍지 않고도 GUI로 확인할 수 있음.

Reference

https://tech.inflab.com/202207-rallit-form-refactoring/react-hook-form/

profile
Jay입니다.

0개의 댓글