오늘은 진행중이던 프로젝트에서 공연 이벤트생성을 위해 사용한 react-hook-form 라이브러리 내역을 기록하려고합니다.
폼 특성상 수많은 값을 관리하거나 보관해야되는데 이를 전부 상태로 관리하게되면 잦은 리렌더링이 예상되기때문에 이같은점을 보완하기위해 react-hook-form을 많이 사용합니다
해당 라이브러리에서는 몇가지 훅을 제공해주는데 대표적으로 useform , register, handleSubmit, watch 등이 있습니다.
import { useForm } from "react-hook-form";
interface FormData {
startEvent: string;
endEvent: string;
name: string; ... 등
const { register, handleSubmit, watch } = useform<FormData>();
먼저 useform 선언해 제공해주는 훅들을 불러올 수 있습니다.
const isAdult = **watch**("isAdult")
<form onSubmit={handleSubmit(onSubmit)}>
<input
{...register("isAdult")}
type="radio"
value="true"
id="adult"
/>
<div>{isAdult}</div>
<button type="submit">제출</button>
</form>
register를 사용하면 이름을 지정해 따로 useState나 상태관리 라이브러리 없이 폼에 입력된 값을 관리할 수 있게되는데 이값을 watch를 사용하면 해당값에 어떤값이 입력되는지 확인이 가능하며 handleSubmit를 사용해 제출이 가능합니다
또한, register를 사용하면 유효성검사기능도 가볍게 구현할수 있게되는데
{...register("place", {
required: "주소는 필수 입력입니다.",
minLength: {
value: 2,
message: "2자리 이상 입력해주세요.",
},
})}
이같이 required는 true,false로 필수값으로 지정도 가능하지만 저렇게 문자열을 입력하게되면 기본값 true 적용됨가 동시에 하단에 입력해달라는 안내문구가 나오게됩니다
minLength와 value로 최소 글자수 지정이 가능하며 지정된 값보다 글자 수가 적게되면 message를 통해 추가적으로 입력해달라는 문구도 지정이 가능합니다
앞서 기본적인 기능에 대해서 적어봤고 실제로 사용하면서 애좀 먹었던 기능들을 기록겸 정리해보겠습니다
공연 시작일과 종료일을 제출해야되는데 DatePicker와 같이사용하기위해 제공해주는 Controller 훅을 사용했습니다.
Controller는 onChange, onBlur와 같은 이벤트 핸들링을 쉽게 할 수 있도록 해줍니다.
<Controller
control={control}
name="endEvent"
render={({ field }) => (
<DatePicker
{...field}
showTimeSelect
dateFormat="yy년 MM월 dd일 aa h시 mm분"
selected={field.value ? dayjs(field.value).toDate() : null}
onChange={(date) => field.onChange(dayjs(date).toDate())}
minDate={minDate ? new Date(minDate) : undefined}
maxDate={maxDate ? new Date(maxDate) : undefined}
/>
)}
/>
name : register와 같이 사용되는 이름
dateFormat: 출력되는 날짜의 포맷을 설정
selected , onChange : 선택되는 날짜의 값을 받아 onChange로 상태값저장
minDate , maxDate : 최소일짜와 최대날짜 지정
배우는 여러명이기에 배열로 제출을 해야되는데
저는 사용자가 편하게 사용할 수 있게 배우명을 입력하고 엔터를 사용하여 많은 값을 입력할수 있도록 구현했습니다
이를 구현하기위해서 register아닌 배열을 관리하는 훅 useFieldArray을 사용했습니다
const {
fields: castingsFields,
append: appendCasting,
remove: removeCasting,
} = useFieldArray({
control,
name: "castings",
});
fields를 사용해 배열을 관리가능하며, append와 remove를 사용해서 배열 끝에 값을 추가및 제거가 가능합니다
const addCasting = (castingName: string): void => {
if (castingName && castingName.length >= 2) {
appendCasting({ name: castingName });
}
};
const handleKeyDown = (
event: KeyboardEvent<HTMLInputElement>,
action: (name: string) => void
) => {
if (event.key === "Enter") {
event.preventDefault();
const name = event.currentTarget.value.trim();
if (name) {
action(name);
event.currentTarget.value = "";
}
}
};
appendCasting을 addCasting에 호출하여 값을 추가하도록 구현했습니다."
handleKeyDown을 작성해 enter시에 새로고침을 막고 값이 입력될수 있게끔 작성했습니다
<div>
<label htmlFor={id}>
{label}
</label>
<input
id={id}
name={id}
placeholder={placeholder}
onKeyDown={onKeyDown}
/>
<div className="flex flex-row">
{fields.map((field, index) => (
<div key={field.id} className="flex
items-center space-x-2 mt-2">
<div>
{field.name}
<button type="button"
onClick={() => remove(index)} >
<IoCloseSharp />
</button>
</div>
</div>
))}
</div>
</div>
생각보다 제공해주는 hook도 많고 상황에 따라 여러 훅을 사용하게 해서 애를 먹었던 react-hook-form 그래도 작성하다보니 상태값으로 하나하나 관리하는거보단 관리하기엔 훨씬 용이하다는 점을 느끼며 포스팅 마무리 해보겠습니다