시작하기 앞서...
React Hook Form 을 공통 컴포넌트에 사용을 하는데 다음과 같은 오류가 발생하였다.
바로 FormInput 이라는 컴포넌트가 ref 를 받을 수 없기 때문이다. 그래서 이를 해결하기 위해 forwardRef
를 사용해야 한다.
React Hook Form 에서 ref 받아야 되는 이유
FormInput 이라는 input 공통 컴포넌트를 사용하고 있다.
React Hook Form 은 내부적으로 ref 를 등록하여 각 폼 요소의 값과 상태를 추적하는 원리로 동작한다. 그래서 React Hook Form 은 register 함수를 사용하여 ref 로 등록하는데 FormInput 컴포넌트에서는 ref 를 전달받지 못해 위에 에러가 발생하는 것이다.
그래서 부모 컴포넌트로부터 자식 컴포넌트의 참조(ref) 를 전달해주는 forwardRef
를 사용해야 되는 것이다.
forwardRef 사용하기
기존 코드
해당 코드에서 extend ComponentProps<'input'>
의 의미는 인터페이스에 HTML input 태그에 들어갈 수 있는 모든 속성을 외부에서 주입할 수 있도록 확장성을 열어둔 것이다. 그러면 label, id, placeholder, type 을 제외하고 input 태그에서 사용할 수 있는 속성들을 FormInput 컴포넌트의 props 로 사용할 수 있게 된다. (onBlur, onChange 등 props 로 사용 가능)
import React, { ComponentProps, memo } from 'react';
import FormWrapper from '@/components/common/FormWrapper';
import style from './style.module.scss';
interface FormInputProps extends ComponentProps<'input'> {
label: string;
id: string;
placeholder: string;
type?: string;
}
const FormInput = ({
label,
id,
placeholder,
type,
...props
}: FormInputProps) => {
return (
<FormWrapper id={id} label={label}>
<input
id={id}
name={id}
placeholder={placeholder}
className={style.input}
type={type}
{...props}
/>
</FormWrapper>
);
};
export default memo(FormInput);
변경 코드
forwardRef
를 사용하여 다음과 같이 수정하였다.
forwardRef
를 사용할 때, 어떤 타입의 요소에 ref 가 연결될지 지정해야 한다. 그래서 컴포넌트의 props 타입은 FormInputProps 와 더불어서, 아래 컴포넌트는 input 이므로 HTMLInputElement 도 같이 타입으로 설정했다.
import React, { ComponentProps, memo, forwardRef } from 'react';
import FormWrapper from '@/components/common/FormWrapper';
import style from './style.module.scss';
interface FormInputProps extends ComponentProps<'input'> {
label: string;
id: string;
placeholder: string;
type?: string;
}
const FormInput = forwardRef<HTMLInputElement, FormInputProps>(
({ label, id, placeholder, type, ...props }, ref) => {
return (
<FormWrapper id={id} label={label}>
<input
id={id}
name={id}
placeholder={placeholder}
className={style.input}
type={type}
ref={ref}
{...props}
/>
</FormWrapper>
);
}
);
FormInput.displayName = 'FormInput';
export default memo(FormInput);
결과
내용에 제대로 입력되고 제출되는 것까지 확인했다. 👍
'💜 리액트 > React' 카테고리의 다른 글
[React] axios 로그인 유저 기능 구현 (feat. 토큰) (0) | 2024.06.17 |
---|---|
개발자 도구로 React 애플리케이션 분석 (0) | 2024.06.15 |
[React] useEffect 클린업(Clean Up) 함수로 메모리 누수 방지 (2) | 2024.06.14 |
[React] 리액트 개발 도구로 디버깅하기 - React Developer Tools (0) | 2024.06.11 |
[React] memo, useMemo, useCallback 사용해서 렌더링 최초화 하기!! (1) | 2024.06.10 |
FE 개발자가 되고 싶은 짱잼이
포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!