React Hook Form은 로컬 폼 상태를 효과적으로 관리하기 위한 라이브러리이다.
useState와 같은 제어 컴포넌트로 form을 관리하면
여러 state 관리, 값을 변경 처리하는 이벤트 핸들러, 불필요한 리랜더링 등.. 때문에 코드 관리가 상당히 번거롭기 때문에 react-hook-form을 사용하여 로컬 폼 상태를 관리하는 것이 좋다!
1.defaultValues로 초기값을 설정하고, mode로 유효성 검사 시점을 정하였다.
예제에서는 keyword 필드의 초기값을 빈 문자열로 설정했고,
onBlur 모드를 사용하여 사용자가 입력 필드에서 포커스를 벗어났을 때 유효성 검사가 실행된다.
import { FormProvider, useForm, useWatch } from 'react-hook-form';
...
// 초기값 설정, 유효성 검사 모드 등 useForm 설정
const methods = useForm<States>({
defaultValues: {
keyword: '',
},
mode: 'onBlur',
});
2.FormProvider은 useForm 훅으로부터 반환된 메서드들의 자식 컴포넌트에게 전달하기 위해 사용된다.
FormProvider를 사용하면 복잡한 컴포넌트 트리에서도 폼의 상태와 메서드를 쉽게 공유하고 재사용할 수 있으며, props를 개별적으로 전달하는 번거로움을 줄일 수 있다.
<FormProvider {...methods}>
<SearchBar
onPress={onPressSearch}
count={data.pages[0].resultData.total || 0}
/>
</FormProvider>
3.useFormContxt를 통해 useForm 반환값을 그대로 사용한다.
searchBar 컴포넌트는 useFormContext를 사용해서 control와 handleSubmit를 직접 접근하여,
컴포넌트가 폼의 상태와 로직을 직접적으로 제어할 수 있게 해준다.
interface ISearchBarProps {
onPress: (keyword: string) => void;
count: number;
}
const SearchBar = (props: ISearchBarProps) => {
const { onPress, count } = props;
const { control, handleSubmit } = useFormContext(); //useForm 반환값
// useController 훅은 name: 'keyword'를 가진 폼 필드를 제어하는데 사용된다.
// 초기값으로 설정했던 Key값과 name이 같아야한다.
// control 객체를 필요로 하고, value, onchange, onBlur 등을 제공한다.
const { field } = useController({
control,
name: 'keyword',
rules: {
required: true,
},
});
const [focused, setFocused] = useState<boolean>(false);
const onPressSearch = () => {
Keyboard.dismiss();
handleSubmit(() => onPress(field.value))();
};
return (
<>
<Style.Container isFocused={focused}>
<Style.TextInput
value={field.value}
onChangeText={field.onChange}
placeholder="ex) 김치볶음밥"
autoCapitalize="none"
autoCorrect={false}
onFocus={() => setFocused(true)}
onBlur={() => {
setFocused(false);
field.onBlur();
}}
onSubmitEditing={() => handleSubmit(onPressSearch)()}
/>
//handleSubmit 함수를 사용하여 폼의 제출을 처리
<Pressable onPress={() => handleSubmit(() => onPress(field.value))()}>
<SearchIcon />
</Pressable>
</Style.Container>
<Font.Count>{`검색: ${customToLocaleString(count)}건`}</Font.Count>
</>
);
};