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;