FieldArray (react-hook-form)

Ryan Cho·2024년 12월 12일
1

useFieldArray

react-hook-form에서 동적으로 필드 배열을 관리하기 위해 제공되는 훅으로 동적으로 복잡한 형태의 데이터구조(여러 체크박스등)를 관리할때 사용한다. 혹은 전화번호 입력 폼 처럼 세개의 입력폼이 분리되어 하나처럼 동작할때라던가. 알아두면 매우 유용함.

기본 사용법

import { useFieldArray, useFormContext } from "react-hook-form";
import RHForm from "./RHForm";
import { z } from "zod";

function FieldArray() {
  const { control, register } = useFormContext();
  const { fields, append} = useFieldArray(
    {
     //control, // RHForm에서 FormPorvider를 사용하기때문에 생략 가능
      name: "test", // 필드 어레이 이름(동적으로 만들면 되겠다)
    }
  );

  return (
    <>
      {fields.map((field, index) => (
        <input
          key={field.id} // 필드 아이디 부여
          {...register(`test.${index}`)} // 필드를 등록하는데 test라는 name(배열)의 인덱스별로 
          								//생성되기때문에 저런식으로 작명하며 defaultValue가 존재해야함
        />
      ))}
      <button
        type="button"
        onClick={() => {
          append("초기값");
        }}
      >
        APPENDBTN
      </button>
      <button type="submit">SUBMIT</button>
    </>
  );
}

const schema = z.object({
  test: z.array(z.string().min(1,'한자 이상 입력하세요')),
});

type FormType = z.infer<typeof schema>;

//필드어레이는 기본값을 바탕으로 동작 !important
const defaultValues = {
  test: ["1", "2", "3"],
};

const FieldArrayPage = () => {
  return (
    <RHForm<FormType> schema={schema} defaultValues={defaultValues}>
      <FieldArray />
    </RHForm>
  );
};

export default FieldArrayPage;

커스텀(제어 컴포넌트)

import { Controller, useFieldArray } from "react-hook-form";
import RHForm from "./RHForm";
import { z } from "zod";

const CheckBoxList = () => {
  //   const { register } = useFormContext();
  const { fields = [] } = useFieldArray({
    name: "test",
  });

  return (
    <>
      {fields.map((field, idx) => {
        const name = `test.${idx}`;
        // const fieldMethods = register(name);

        return (
          <Controller // 2) 그래서 제어컴포넌트를 준비했습니다 => 제어컴포넌트를 쓸때 다시 그리기 위한 컴포넌트
            name={name}
            render={({ field: { onBlur, onChange, value, } }) => {
              return (
                <input
                  key={field.id}
                  type="checkbox"
                  value={value.value}
                  checked={value.checked}
                  name={name}
                  // ref={fieldMethods.ref} // 1) 체크박스에서는 ref를 쓰면 value를 덮어쓰기때문에 비제어 컴포넌트로는 체크박스를 구현할 수 없다.
                  onChange={(e) =>
                    onChange({
                      value: e.target.value,
                      checked: e.target.checked,
                    }) // defaultValue의 폼대로 변경사항을 맞춰줘야하기때문
                  }
                  onBlur={onBlur}
                />
              );
            }}
          />
        );
      })}
    </>
  );
};

const schema = z.object({
    test: z.array(z.object({
        value: z.string(),
        checked: z.boolean()
    }))
});


// 체크박스 defaultValue, checked:boolean에 따라 체크박스의 checked 속성 활성화,
//value는 체크박스에 대한 내용이 오면 되겠다.
const defaultValues = { 
  test: [
    {
      value: "1",
      checked: false,
    },
    {
      value: "2",
      checked: false,
    },
    {
      value: "3",
      checked: true,
    },
  ],
};

const FieldArrayCheckBoxPage = () => {
  return (
    <RHForm schema={schema} defaultValues={defaultValues}>
      <CheckBoxList />
    </RHForm>
  );
};

export default FieldArrayCheckBoxPage;
profile
From frontend to fullstack

0개의 댓글