[React] Function components cannot be given refs. Attempts to access this ref will fail. Did you mean to use React.forwardRef()?
1. 에러 발생
회원가입, 로그인 기능을 구현하기 위해 input 태그에 value를 입력받고, 필요한 경우 입력된 value에 대해 유효성 검사를 실시하고, 유효하지 않은 value가 입력되었을 시 에러 메시지를 출력하는 과정이 필요했습니다.
기능 구현 방법에 대해 고민하던 중 비제어 컴포넌트 방식으로 구현되어 있어 사용자의 입력에 따른 렌더링 횟수를 줄일 수 있는 React Hook Form을 사용하기로 결정했습니다.
각 페이지에 여러개의 input 태그가 존재했고, 구현해야 하는 각각의 input 태그의 형태와 기능이 유사했기 때문에 이를 재사용 컴포넌트로 만들고자 했습니다.
// Input.tsx; Warning 메시지 발생 코드
const Input = ({
label,
type = 'text',
placeholder,
...props
}: InputProps) => {
const ref = useRef(null);
return (
<InputContainer>
{label && <label>{label}</label>}
<StyledInput type={type} placeholder={placeholder} ref={ref} {...props} />
</InputContainer>
);
};
export default Input;
React Hook Form은 비제어 컴포넌트를 기반으로 구현되어 있었고, 비제어 컴포넌트를 만들기 위해서는 ref를 사용해야 했기 때문에 위와 같이 ref를 선언하고, ref를 input 태그에 전달하여 컴포넌트를 만든 후 회원가입 페이지에 적용하자 다음과 같은 Warning 메시지가 발생했습니다.
Warning: Function components cannot be given refs. Attempts to access this ref will fail. Did you mean to use React.forwardRef()?
Warning 메시지는 '함수 컴포넌트는 ref를 받을 수 없고, 해당 ref에 접근하려고 시도하면 실패할 것입니다. React.forwardRef()를 사용하려고 했나요?' 라는 의미였습니다.
2. 에러 해결
방법) React.forwardRef API 사용
// Input.tsx;
// React.forwardRef 적용
const Input = React.forwardRef<HTMLInputElement, InputProps>(
({ type = 'text', placeholder, label, ...props }: InputProps, ref) => {
return (
<InputContainer>
{label && <label>{label}</label>}
<StyledInput
type={type}
placeholder={placeholder}
ref={ref}
{...props}
/>
</InputContainer>
);
}
);
Input.displayName = 'Input';
export default Input;
3. 고찰
본 Warning 메시지를 해결하며 공식문서를 통해 리액트에서 ref를 forwarding 하는 방법에 대해 학습할 수 있었습니다. 또한, 회원가입, 로그인 기능을 구현하기 위한 방법을 고민하고, 라이브러리의 공식 문서를 읽어보며 잘 알지 못했던 제어 컴포넌트, 비제어 컴포넌트의 개념에 대해 학습할 수 있는 시간이였습니다.