React-Hook-Form의 FormProvider, useFormCotext

yii·2025년 3월 12일
post-thumbnail

📌문제

포트폴리오 페이지를 구현하며 포트폴리오 -> 포트폴리오 각 입력 섹션-> 입력 필드로 register을 props로 전달하며 props drilling이 발생하였다.

포트폴리오 작성 페이지에서 섹션, 아이템까지 폼 데이터를 전달하는 더 나은 방법에 대해 고민하게 되었다.

FormProvider, useFormProvider 사용법

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)
  const { register, reset } = methods


  useEffect(() => {
    reset({
      name: "data",
    })
  }, [reset]) // ❌ never put `methods` as the deps


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


function NestedInput() {
  const { register } = useFormContext() // retrieve all hook methods


  return <input {...register("test")} />
}
 

제일 상단에 <FormProvider {...methods}>를 배치시키면 하위 컴포넌트에서 useFormContext를 사용해 form에 접근을 할 수 있게 된다.

function NestedInput() {
  const { register } = useFormContext() // retrieve all hook methods


  return <input {...register("test")} />
}

input,textarea 등의 태그에서 register을 다음과 같이 사용해 등록하면 된다.

useFormContext는 어떻게 동작할까?

useFormContext는 React 컴포넌트 트리 안에서 Form의 상태와 메서드에 접근할 수 있게 해주는 Hook이다. Context API를 기반으로 동작하며, 이를 통해 Form 컴포넌트에서 Form의 상태를 공유하고 관리할 수 있다.

Context API를 기반으로 하였지만 useFormContext는 From의 상태와 메서드에 대한 접근을 편리하게 해주어 Form 관련 로직을 효율적으로 관리할 수 있기 때문에 성능 측면에서 차이점이 있다.

useFormContext는 언제 사용하는 것이 좋을까?

Context API를 사용하면 컴포넌트 트리의 깊은 곳까지 상태를 전파하기 때문에 성능에 영향을 줄 수 있다. 폼 상태가 변경될 때 하위 컴포넌트가 재랜더링될 수 있기 때문이다. 따라서 간단한 폼보다 폼을 여러 컴포넌트로 분리해야 하거나, 중첩된 폼을 관리하거나, 코드 재사용성을 높이고 싶을 때 사용하는 것이 좋다.

import React, { memo } from "react";
import { useFormContext } from "react-hook-form";

const SectionComponent = memo(() => {
  const { register, formState: { isDirty } } = useFormContext();

  return (
    <div>
      <input {...register("sectionName")} />
      {isDirty && <p>This field is dirty</p>}
    </div>
  );
}, (prevProps, nextProps) => prevProps.formState.isDirty === nextProps.formState.isDirty);

성능 최적화를 위해 React.memo 를 사용하여 불필요한 재랜더링을 방지할 수 있다.

PPLOG에서의 FormProvider, useFormContext를 활용하여 코드를 개선해보자

(추가)

참고

https://react-hook-form.com/docs/formprovider
https://react-hook-form.com/docs/useformcontext

0개의 댓글