레포지토리 설명
폼 데이터 관리 관리를 위한 도구들을 제공하는 react-hook-form
ISSUE 링크
PR링크
문제 상황
아래처럼 FormProvider 내부에 위치한 컴포넌트에서
export default function App() {
// ...
return (
<FormProvider {...methods}>
<MyForm />
</FormProvider>
);
}
JavaScript
복사
useForm에서 제공하는 setError를 useEffect내부에서 사용 시 에러메세지가 업데이트 되지 않는 문제점이 있었다.
function MyForm() {
// ...
useEffect(() => {
// setError를 사용해도 에러 메세지가 추가되지 않음
setError("firstname", { type: "manual", message: "This is an error" });
}, [setError]);
return (
// ...
<input {...register("firstname")} placeholder="firstname" />
{errors.firstname && <p>errors.firstname.message</p>}
// ...
);
}
TypeScript
복사
원인 파악
useForm의 동작을 확인하기 위해 useForm.ts 파일의 내용을 확인해보았다.
useForm 내부에서 _subscribe 함수를 사용해
// src/useForm.ts
export function useForm<
// ...
React.useEffect(
() =>
control._subscribe({
formState: control._proxyFormState,
callback: () => updateFormState({ ...control._formState }),
reRenderRoot: true,
}),
[control],
);
// ...
TypeScript
복사
const _subscribe: FromSubscribe<TFieldValues> = (props) =>
_subjects.state.subscribe({
next: (
formState: Partial<FormState<TFieldValues>> & {
name?: InternalFieldName;
values?: TFieldValues | undefined;
},
) => {
if (
shouldSubscribeByName(props.name, formState.name, props.exact) &&
shouldRenderFormState(
formState,
(props.formState as ReadFormState) || _proxyFormState,
_setFormState,
props.reRenderRoot,
)
) {
props.callback({
values: { ..._formValues } as TFieldValues,
..._formState,
...formState,
});
}
},
}).unsubscribe;
TypeScript
복사
해결방안
느낀점
React.useLayoutEffect(() => {
const unsubscribe = control._subscribe({
formState: control._proxyFormState,
callback: () => {
updateFormState({ ...control._formState });
},
reRenderRoot: true,
});
return () => {
unsubscribe();
};
}, [control]);
JavaScript
복사
React.useLayoutEffect(() => control._subscribe({
formState: control._proxyFormState,
callback: () => {
updateFormState({ ...control._formState });
},
reRenderRoot: true,
}),
[control],
);
JavaScript
복사