
시작하기 앞서...
최근 진행했던 프로젝트에서 편지 글 쓰기 페이지
를 구현을 했는데 이를 구현하기 위해 React-Hook-Form 을 사용하고 있다.
그런데 개발하면서 정말 좋고 편리한 기능이 있어 이렇게 글을 작성하게 되었다.
실제로 개발을 하다보면 여러 컴포넌트가 생기게 된다.
이럴 때 매번 props 로 컴포넌트간 데이터를 다 전달하기엔 너무 복잡하고 힘이 든다. (prop drilling
이 발생)
이러한 상황에서 쉽게 폼 데이터를 사용하는 방법이 바로 FormProvider 이다!!!!!!!

또한 개발을 할 때, 폼에 제출할 내용이 input, textarea, select 이런 태그가 아닐 때도 발생한다.
아래 사진은 내가 현재 구현한 페이지인데 input 태그로 만들지 않은 것들은 {...register('이름')}
로 React-Hook-Form 에 등록하지 못한다.
이럴 땐 setValue 를 통해 form 에 데이터를 넣을 수 있다.

설명하기 앞서, 만약 React-Hook-Form 에 대해 모른다면 [해당 게시물] 에서 확인하고 오는 것을 추천한다.
FormProvider
세팅하기
먼저 useForm 과 FormProvider 를 가져온다.
useForm
폼의 상태를 관리하고 제어하기 위한 것들을 객체로 가짐
FormProvider
하위 컴포넌트에 폼 상태 및 메소드를 전달
import { useForm, FormProvider } from 'react-hook-form';
그리고 methods
는 useForm 을 통해 반환된 객체이며,
methods
를 통해 폼 제출을 처리하는 handleSubmit
메서드를 가져온다.
const methods = useForm();
const { handleSubmit } = methods;
이제 FormProvider 를 사용할 준비가 끝났다.
적용하기
제일 상단에 <FormProvider {...methods}>
를 배치한다.
그러면 여러 하위 컴포넌트에서 useFormContext 를 사용하여 form 에 대해 접근을 할 수 있게 된다.
return (
<FormProvider {...methods}>
<div css={style.container}>
...
<form onSubmit={handleSubmit(onSubmit)} css={style.contentWrapper}>
<LetterWriteContent />
<LetterWriteBottom />
</form>
...
</div>
</FormProvider>
);
useFormContext
FormProvider 로 하위에 쉽게 접근하게 되었고 하위에서는 useFormContext 를 사용하여 해당 폼 객체에 대해 접근을 한다.
import { useFormContext } from 'react-hook-form';
register
하위 컴포넌트가 input, textarea, select 태그면 register 를 사용해 등록해준다.
const { register } = useFormContext();
return (
<textarea
{...register('content')} /** register 로 등록 */
name="content"
rows={15}
autoFocus
placeholder="하고싶은 이야기를 적어보세요."
css={style.textarea}
maxLength={letterWrite.content.max.value}
/>
);
setValue, watch
하위 컴포넌트가 input, textarea, select 태그가 아닌 것이라면 setValue 와 watch 를 사용해서 구현해준다.
setValue
폼 필드의 값을 변경&설정 할 때 사용
watch
폼 필드의 현재 값을 가져올 때 사용
칩 버튼을 눌러 클릭하면 setValue 를 통해 선택한 값을 폼 필드에 넣고
watch 를 통해 폼에 들어간 현재 값을 확인할 수 있다.
const { setValue, watch } = useFormContext();
return (
<section>
<div>
{chipLabels.map((label) => (
<Chip
key={label}
variant={watch('concern') === label ? 'form-selected' : 'form'}
onClick={() => setValue('concern', label)}
>
{label}
</Chip>
))}
</div>
</section>
);
};
export default ConcernSelect;
/** 실제 코드는 이렇게 구현 안함 */
이렇게 구현하였다!
폼 제출
버튼 type="submit"
폼 제출 버튼은 버튼 타입을 submit
으로 설정하면 해당 버튼을 누를 시 폼이 제출된다. 나머지 버튼은 타입을 button 으로 해주었다.
<Button
onClick={() => navigate(ROUTER_PATHS.ROOT)}
type="button"
variant="secondary"
size="sm"
>
뒤로
</Button>
<Button type="submit" variant="primary" size="sm">
보내기
</Button>
onSubmit
위에서 이런식으로 코드를 작성했었는데, onSubmit 에 폼이 제출될 때 호출될 함수를 지정한다.
<form onSubmit={handleSubmit(onSubmit)} css={style.contentWrapper}>
<LetterWriteContent />
<LetterWriteBottom />
</form>
그래서 함수를 만들고 폼에 입력받은 값들을 출력하면 정상적으로 출력되는 것을 확인할 수 있다.
const onSubmit = (date: object) => {
console.log(data);
};
👍👍👍
마치며...
지난 프로젝트에도 글을 작성하는 부분을 맡았었는데 그때에는 React-Hook-Form 을 몰라 상태관리 라이브러리인 Recoil 을 사용해서 구현했었다. 그리고 일일히 유효성 검사도 하고 정말 힘이 들었었다...🥲
하지만 이번 프로젝트에서는 React-Hook-Form 과 Zod 를 사용하였고 이를 사용하여 구현을 하니 훨신 form 을 구현하기가 쉬웠고 코드도 간결해지고 파악하기 쉬웠다... 정말 최고 👍👍👍 좋은 지식과 경험을 더 쌓아가는 것 같아 너무 만족스럽고 좋았다.
(React-Hook-Form 의 [공식문서] useformcontext 와 [공식문서] formProvider 에 대한 자세한 내용은 공식문서에서 확인할 수 있다.)
FormProvider
Performant, flexible and extensible forms with easy-to-use validation.
react-hook-form.com
useFormContext
Performant, flexible and extensible forms with easy-to-use validation.
react-hook-form.com
'💜 프로젝트 구현' 카테고리의 다른 글
[React] getFetch 커스텀 훅 hook 만들기 (0) | 2024.06.03 |
---|---|
[Github Action] Organization 레포지토리 vercel 미리보기 preview 배포 (0) | 2024.05.09 |
[Github Action] 깃허브 Organization 레포지토리 vercel 자동 배포 (0) | 2024.05.07 |
Zod enum 타입 error message 변경 방법 (0) | 2024.03.24 |
React Query(Tanstack Query) 의 staleTime 사용 방법 (1) | 2024.03.12 |
FE 개발자가 되고 싶은 짱잼이
포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!