React-hook-form for nested objects

JM·2023년 7월 20일
0
post-custom-banner

react-hook-form 을 이용해 2차원 이상의 배열을 다뤄야했다.

다행히 폼 라이브러리의 문서에 잘 정리되어 있어서 어렵지 않게 구현하였다. 핵심은 useFieldArray 이다.

예제 코드를 위해 최대한 간단하게 구현해보았다.

import { useForm, useFieldArray, UseFormReturn } from 'react-hook-form';

interface IFormProps {
  files: Array<IFile>;
}

interface IFile {
  url: string;
  images: Array<IImage>;
}

interface IImage {
  url: string;
  altText: string;
}

const MainForm: React.FC = () => {
  const form = useForm<IFormProps>();

  const { register, handleSubmit, control } = form;

  const { fields, append, remove } = useFieldArray({
    control,
    name: 'files',
  });

  const onSubmit = (data: IFormProps) => {
    console.log(data);
  };

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      {fields.map((item, index) => {
        return (
          <div key={index}>
            <input type="text" {...register(`files.${index}.url`)} />

            {/* Nested form */}
            <ImagesForm fileIndex={index} form={form} />

            <button type="button" onClick={() => remove(index)}>
              파일 삭제
            </button>
          </div>
        );
      })}

      <button type="button" onClick={() => append({ url: '', images: [] })}>
        파일 추가
      </button>
    </form>
  );
};

const ImagesForm: React.FC<{ fileIndex: number; form: UseFormReturn<IFormProps> }> = ({
  fileIndex,
  form: { register, control },
}) => {
  const { fields, append, remove } = useFieldArray({
    control,
    name: `files.${fileIndex}.images`,
  });

  return (
    <div>
      {fields.map((item, index) => {
        return (
          <div key={index}>
            <input type="text" {...register(`files.${fileIndex}.images.${index}.url`)} />
            <input type="text" {...register(`files.${fileIndex}.images.${index}.altText`)} />
            <button type="button" onClick={() => remove(index)}>
              이미지 삭제
            </button>
          </div>
        );
      })}
      <button type="button" onClick={() => append({ url: '', altText: '' })}>
        이미지 추가
      </button>
    </div>
  );
};

export default MainForm;

참고: https://react-hook-form.com/docs/usefieldarray
왠지 모르겠지만 공식 문서에는 Nested Form 예제에 타입스크립트 코드가 없다 (...)

profile
No one's perfect, but still striving for perfection
post-custom-banner

1개의 댓글

comment-user-thumbnail
2023년 7월 20일

좋은 글 감사합니다!

답글 달기