링크
React Hook Form - performant, flexible and extensible form library
Performant, flexible and extensible forms with easy-to-use validation.
react-hook-form.com
강의 동영상을 무료로 제공해준다고..?
개요
난 개인프로젝트를 해왔고 서버에 무언갈 post하고 patch할 일이 거의 없었다.
하지만 협업프로젝트에서 복잡한 form을 구축하고 그 데이터를 백엔드에 보내야 할 일이 있었다.
바닐라하게 작성한다면 엄청난 상태를 정의해야하고, 그만큼 빈번한 리랜더링이 일어나고, 복잡한 예외처리와 검증을 해야한다. 코드짜는 난이도가 기하급수적으로 늘어난다. 으악 싫어
내 요구사항을 들은 팀원분이 react-hook-form을 권유했고 적용해서 나 역시도 폼을 짜잘하게 컴포넌트화하고 커스텀훅도 작성하는 등 좋은 개발경험을 가졌다.
사용환경
React MUI(+cssInJs) react-hook-form
내가 사용한 것
FormInfoDataType 커스텀 타입
export interface FormInfoDataType {
username: string
bio: string
sex: 'MALE' | 'FEMALE' | 'OTHER'
}
여기서 쓰는 폼 데이터이다.
const EditProfile = ({data}: PropType) => {
const methods = useForm<FormInfoDataType>({
defaultValues: {
username: data.username,
bio: data.bio,
sex: data.sex,
},
})
}
useForm을 이용해 처음에 폼에 들어갈 데이터를 정의했다.
나같은 경우엔 정보변경을 요구받아서 data에 유저가 설정한 정보를 담았고 그걸 defaultValues로 설정했다.
딱히 validation은 요구받지 않았다.
form에서 제출버튼을 눌렀을때 작동할 함수(여기선 onSubmit)를 handleSubmit()에 넣는다.
onSubmit
const usePostProfile =() => {
const profile = useMutation(
(d: {bio: string; username: string; sex: 'MALE' | 'FEMALE' | 'OTHER'}) => patchProfile(d),
{
onSuccess: () => {
alert('프로필 정보 변경 성공')
},
onError: () => {
alert('프로필 정보 변경 실패')
},
useErrorBoundary: false,
},
)
const onSubmit = (data: FormInfoDataType) => {
try {
profile.mutate({...data})
} catch (error: any) {
alert(error.message)
}
}
return {onSubmit}
}
const EditProfile = ({data}: PropType) => {
const methods = useForm<FormInfoDataType>({
defaultValues: {
username: data.username,
bio: data.bio,
sex: data.sex,
},
})
const {onSubmit} = usePostProfile()
return (
<Container>
<FormProvider {...methods}>
<form onSubmit={methods.handleSubmit(onSubmit)}>
<EditInfo />
</form>
</FormProvider>
</Container>
)
}
폼이 복잡해지면 컴포넌트화를 해야한다. 그것은 props drilling을 발생시킨다.
하지만 react-hook-form엔 FormProvider이라는 강력한 기능이 있고, useFormContext를 통해 props drilling없이 자식내에서 접근 가능하다.
이제 자식 컴포넌트인 EditInfo에서 Formdata를 접근하고 제어해보자
const EditInfo = () => {
const {bio,username} = useEditProfileForms()
return (
<>
<EditTitle title="내 정보">
<FormLabel>닉네임</FormLabel>
<Input placeholder="닉네임" {...username.field} />
<FormLabel>내 소개</FormLabel>
<Input width="717px" placeholder="내 소개" {...bio.field} />
<FormLabel>성별</FormLabel>
<SexRadio />
</EditTitle>
{/*submit 역할을 하는 버튼*/}
<SaveButton>저장하기</SaveButton>
</>
)
}
Custom hook: useEditProfileForms
const useEditProfileForms = () => {
const {control} = useFormContext<FormInfoDataType>()
const username = useController({
name: 'username',
control,
})
const bio = useController({
name: 'bio',
control,
})
const sex = useController({
name: 'sex',
control,
})
return {control, username, bio, sex}
}
export default useEditProfileForms
form provider에서 내려주고 있는 데이터에 접근한다.
난 MUI를 사용하고 있어서 useForm()의 resister에 직접 접근하는 대신 useController(name,control,(rules))를 사용했다.
name에는 formData에서 어떤걸 사용할건지 key값을 넣고 control에는 formprovider에서 내려주는 method들의 contorl을 넣어줬다.
위 커스텀훅은 닉네임,성별,소개를 리턴해줘서 각각의 인풋을 제어할 수 있게한다.
필드
<Input width="717px" placeholder="내 소개" {...bio.field} />
필드를 이용해 내 인풋 컴포넌트로 onChange, onBlur, value, disabled, name, ref를 설정한다.
라디오 형식 인풋에서의 사용
const Arr = [
{label: '남성', value: 'MALE'},
{label: '여성', value: 'FEMALE'},
{label: '선택하지않음', value: 'OTHER'},
]
const SexRadio = () => {
const {sex} = useEditProfileForms()
return (
<RadioGroup
{...sex.field}
>
{Arr.map((e, i) => (
<FormControlLabel
key={i}
control={<Radio size="small" />}
label={e.label}
value={e.value}
/>
))}
</RadioGroup>
)
}
라디오 그룹에 필드를 넣어준다.
각각의 FormControlLabel 또는 <Radio/>에 넣으면 안된다. 각각의 라디오는 성별 하나씩 매칭되기 때문에.. 남/여/other 중 하나를 제출할 수 있는 기능이 없다.
요약
useForm에 defaultValues를 설정하고 리턴받은 method들을 formprovider에 넣어준다.
form태그엔 submit함수를 넣어준다.
자식컴포넌트 안에선 useFormContext로 접근하고 controller를 리턴받는다. useContorller로 각각의 폼데이터에 맞는 name,rule,controller를 설정한다. 리턴받은 각각의 field로 input을 제어한다.
'개발' 카테고리의 다른 글
react-hook-form 폼 유효성 검사기능을 추가한 뒤 submit이 안될 때 (0) | 2024.01.07 |
---|---|
반복되는 컴포넌트 key에 index를 넣으면 안되는 이유 (0) | 2024.01.03 |
React useState에 대해 궁금해졌다 1 (0) | 2023.12.15 |
typescript나 eslint 사용하지 않는 param,변수로 인해 에러를 일으킬 경우 해결법 (0) | 2023.12.15 |
css react프로젝트에서 스크롤바로 인한 잉여부분이 생길 시 해결법 (0) | 2023.12.09 |