레포지토리 설명
폼 데이터 관리 관리를 위한 도구들을 제공하는 react-hook-form
ISSUE 링크
PR링크
문제 상황
•
useForm의 errors 속성의 값으로 {}를 넣으면 무한 랜더링이 발생하는 상황
export const FormAmountShowcase = () => {
const formProps = useForm<{ foo: string }>({
defaultValues: { foo: "bar" },
errors: {},
});
return (
<FormProvider {...formProps}>
<FormComp />
</FormProvider>
);
};
JavaScript
복사
원인 파악
•
useForm.ts에서 errors가 쓰이는 곳은 두군데였다
◦
함수 상단에 props로 들어온 error를 받아 state를 선언해주고
◦
useEffect에서 _setErrors 메서드를 통해 업데이트를 해주는데 쓰이고 있다
// useForm.ts
export function useForm<
// ...
>(
// ...
const [formState, updateFormState] = React.useState<FormState<TFieldValues>>({
// ...
errors: props.errors || {},
// ...
});
// ...
JavaScript
복사
// ...
React.useEffect(() => {
if (props.errors) {
control._setErrors(props.errors);
}
}, [props.errors, control]);
// ...
JavaScript
복사
해결방안
•
무한 랜더링을 막기 위해 빈 객체{} 가 아닐 때만 세터함수가 실행되도록 하였다
React.useEffect(() => {
if (props.errors && Object.keys(props.errors).length > 0) {
control._setErrors(props.errors);
}
}, [props.errors, control]);
JavaScript
복사
•
이미 프로젝트에 동일한 로직으로 체크하는 유틸함수가 있다는 코멘트를 받아 적용하였다.
React.useEffect(() => {
if (props.errors && !isEmptyObject(props.errors)) {
control._setErrors(props.errors);
}
}, [props.errors, control]);
JavaScript
복사
느낀점
•
테스트가 많고 체계적이라 배울점이 많았다.
◦
기여하면서 케이스에 대해 공부하면 학습에도 많은 도움이 될 것 같았다
◦
cypress를 통한 e2e 테스트와 jest, RTL을 통한 유닛, 통합 테스트가 모두 있어서 체계적으로 관리된다는 인상을 받았다
•
React-Hook-Form에 첫 PR이라 너무 서둘렀던 것 같다
◦
isEmptyObject의 존재는 작업을 하면서 생각했었는데 까먹고 그냥 작성하였다;;
◦
{} 외에도 다른 값들의 대해서도 조금 더 테스트를 해봤으면 좋았을 것 같다
▪
{} 가 채워진 프로퍼티라고 해도 랜더링이 반복되는 것은 매한가지이다
▪
useForm이 선언 된 스코프 밖에서 상수로 선언하면 문제는 해결 되겠지만
▪
유저의 기대치와는 조금 동떨어진 방식이라는 느낌을 받았다.
▪
errors prop이 그 특성상 자주 활용하지 않는다는 면에서 소외되어 있다는 느낌을 받았다