라이브러리/React Hook Form

[React Hook Form] useFieldArray 사용법

눙엉 2024. 2. 16. 00:08

폼을 작성할 때 폼 양식을 추가하거나 삭제하는 경우가 생깁니다. 예를 들어, 여러 명의 직원을 추가하거나 삭제하는 폼을 만들 때, useFieldArray를 사용하여 폼 데이터를 유연하게 관리할 수 있습니다. 이를 통해 폼의 양식을 동적으로 조작할 수 있습니다.

 

아래의 코드 예시를 통해, 직원의 이름과 나이를 받아 폼을 작성하고 추가, 삭제, 수정하는 방법을 확인해 보겠습니다.

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

interface Form {
  person: { name: string; age: string }[];
}

const Page = () => {
  const { control, register } = useForm<Form>({
    defaultValues: { person: [{ name: "", age: "" }] },
  });
  const { fields, append, remove, update } = useFieldArray({
    control,
    name: "person",
  });

  const handleAddPerson = (): void => {
    append({ name: "", age: "" }, { shouldFocus: false });
  };

  const handleDeleteLastPerson = (): void => {
    remove(fields.length - 1);
  };

  const handleUpdatePerson = (): void => {
    update(1, { name: "수정", age: "1" });
  };

  return (
    <>
      <button type="button" onClick={handleAddPerson}>
        추가
      </button>
      <button type="button" onClick={handleDeleteLastPerson}>
        삭제
      </button>
      <button type="button" onClick={handleUpdatePerson}>
        수정
      </button>
      {fields.map((field, i) => (
        <>
          <input key={field.id + 1} {...register(`person.${i}.name`)} />
          <input key={field.id + 2} {...register(`person.${i}.age`)} />
        </>
      ))}
    </>
  );
}

 

폼 상태를 추가, 삭제, 수정하는 기능을 각 각의 코드로 이어서 설명하겠습니다.

const handleAddPerson = (): void => {
  append({ name: "", age: "" }, { shouldFocus: false });
};

추가 버튼에 연결된 handleAddPerson 함수를 통해 person 배열에 새로운 객체가 추가됩니다. 이 객체는 name과 age라는 두 속성을 기본값으로 가지고 있습니다. 추가 버튼을 클릭하면 새로 생성된 첫 번째 입력 필드에 자동으로 포커스가 이동하는데, 이 동작을 제어하려면 append 메서드의 두 번째 인자로 focusOptions를 설정할 수 있습니다.

다시 말해, append 메서드는 두 가지 파라미터를 받습니다. 첫 번째 파라미터는 추가할 객체이며, 두 번째 파라미터는 추가 후의 동작을 제어하는 옵션입니다. focusOptions를 이용하여 새로 생성된 필드에 자동 포커스를 설정하지 않을 수 있습니다.

 

const handleDeleteLastPerson = (): void => {
  remove(fields.length - 1);
};

remove 메서드를 사용할 때, fields 배열의 길이에서 1을 뺀 값으로 마지막 요소를 삭제하는 것을 확인할 수 있습니다.

remove 메서드는 삭제할 요소의 인덱스를 인자로 받습니다. fields.length - 1을 통해 person 배열의 마지막 요소를 삭제합니다. 만약 remove의 인자를 작성하지 않으면 연결된 배열의 모든 요소가 삭제됩니다.

 

const handleUpdatePerson = (): void => {
  update(1, { name: "수정", age: "1" });
};

update 메서드는 첫 번째 인자로 요소가 추가될 인덱스를, 두 번째 인자로는 추가할 데이터를 받습니다.

위의 코드에서 update(1, { name: "수정", age: "1" })Person 배열에서 인덱스가 1인 요소를 찾아 해당 요소의 데이터를 주어진 값으로 업데이트합니다. 이로써 특정 위치에 있는 폼 필드의 값을 수정할 수 있습니다. 첫 번째 인자에 전달한 인덱스에 해당하는 요소가 없으면 새로운 요소가 추가됩니다.

 

append(); // X

append({}); // X

append({ name: "", age: ""}); // O

append, prepend, insert, update 메서드를 사용할 때는 빈 객체를 추가할 수 없으며, 객체 내부의 모든 기본 값을 추가해주어야 합니다.

 


폼을 동적으로 관리하는 방법을 알게 되었습니다. 하지만 update 메서드와 setValue의 차이, Controlled Field Array에 대해서는 공식문서와 Chat GPT를 사용해도 아직 어떻게 사용해야 되는지 이해가 잘 되지 않았습니다. 더 많은 경험을 통해 알게 되는 정보들을 추가로 작성해야 될 것 같습니다. 혹시 알고 있는 분들이 댓글을 통해서 조언해 주시면 감사하겠습니다 :)