Search
⚠️

(작성 중) fix: FormProvider 사용 시 useEffect 내부에 있는 setError가 동작하지 않는 버그 수정

PR링크
레포
react-hook-form
상태
release 완료
유형
동작 수정
테스트코드 추가

레포지토리 설명

폼 데이터 관리 관리를 위한 도구들을 제공하는 react-hook-form

ISSUE 링크

12632
issues

PR링크

문제 상황

아래처럼 FormProvider 내부에 위치한 컴포넌트에서
export default function App() { // ... return ( <FormProvider {...methods}> <MyForm /> </FormProvider> ); }
JavaScript
복사
useForm에서 제공하는 setErroruseEffect내부에서 사용 시 에러메세지가 업데이트 되지 않는 문제점이 있었다.
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
복사