본문으로 바로가기

[React] react-hook-form - 4 (useFormContext)

컴포넌트가 커지는 경우 작은 컴포넌트로 1개의 컴포넌트를 나누기 시작한다. 즉, 1개의 컴포넌트를 만들기 위해 여러 컴포넌트를 사용한다. 이러한 경우 react에서 전역변수 개념인 useContext를 이용하면 하위 자식 컴포넌트에서 쉽게 부모 컴포넌트의 값에 접근할 수 있다. react-hook-form에서도 이러한 개념을 제공해주고 있다. useFormContext를 사용하면 FormProvider 자식 컴포넌트들은 부모 값을 쉽게 사용할 수 있다. 간단하게 알아보자. (홈페이지 참고 : 이동하기)

useFormContext 사용하기

import {
  Controller,
  FormProvider,
  useFieldArray,
  useForm,
  useFormContext
} from "react-hook-form";

const initValue = {
  foods: [],
  text: "",
  number: ""
};

const Foods = props => {
  const { control } = useFormContext();
  const { append, fields } = useFieldArray({
    control: control,
    name: "foods"
  });

  return (
    <div>
      <h3>Foods</h3>
      {fields.map((item, index) => (
        <div style={{ marginBottom: 10 }} key={index}>
          <div>
            <span>순위 : </span>
            <Controller
              control={control}
              name={`foods[${index}].rank`}
              render={({ field }) => {
                return <input {...field} />;
              }}
            />
          </div>
          <div>
            <span>음식 : </span>
            <Controller
              control={control}
              name={`foods[${index}].name`}
              render={({ field }) => {
                return <input {...field} />;
              }}
            />
          </div>
        </div>
      ))}
      <button
        onClick={() => {
          append({ name: "음식 이름 입력해주세요.", rank: 0 });
        }}
      >
        추가
      </button>
    </div>
  );
};

const TextNumber = props => {
  const { control } = useFormContext();

  return (
    <div style={{ marginTop: 20 }}>
      <div style={{ marginBottom: 20 }}>
        <span style={{ marginRight: 10 }}>Text</span>
        <Controller
          control={control}
          name="text"
          render={({ field }) => {
            return <input {...field} />;
          }}
        />
      </div>
      <div>
        <span style={{ marginRight: 10 }}>Number</span>
        <Controller
          control={control}
          name="number"
          render={({ field }) => {
            return <input {...field} />;
          }}
        />
      </div>
    </div>
  );
};

const Basic = props => {
  const methods = useForm({
    mode: "onSubmit",
    defaultValues: initValue
  });

  const onSubmit = data => console.log(data);

  return (
    // #1 컴포넌트 구조
    <FormProvider {...methods}>
      <form onSubmit={methods.handleSubmit(onSubmit)}>
        <Foods />
        <TextNumber />
        <div style={{ margin: "10px 0" }}>
          <input type="submit" />
        </div>
      </form>
    </FormProvider>
  );
};

export default Basic;

#1 컴포넌트 구조

코드를 확인해보면 FormProvider안에 자식 컴포넌트로 Foods, TextNumber 컴포넌트 2개가 있다. 즉 Foods, TextNumber 컴포넌트는 FormProvider에서 제공해준 {...methods}를 사용할 수 있다는 것이다.

 

사실 위 코드에서 설명한 내용은 너무 없다. 이전 게시글에서 설명한 내용을 다 이해했으면 이해가 다 될 것이고 만약 이해가 되지 않은 내용이 있다면 아마 react useContext에 대한 이해가 부족한 것으로 추측이 된다. useContext hook을 검색 후 이해하는 것이 우선인 것 같다.

마지막

해당 내용은 틀릴 수도 있다는 것을 감안하여 봐주세요. 틀린 내용 및 오탈자 수정 요청 환영입니다.

반응형