컴포넌트가 ref를 받아 하위 컴포넌트로 전달하도록하려면 forwardRef를 사용해야한다.
예시 코드
import { forwardRef } from 'react';
const MyInput = forwardRef(function MyInput(props, ref) {
// ...
});
ex) input
에 focus
할 때 사용하는 방법
Edit 버튼을 클릭하면 자동으로 input에 focus된다
import { useRef } from 'react';
import MyInput from './MyInput.js';
export default function Form() {
const ref = useRef(null);
function handleClick() {
ref.current.focus();
}
return (
<form>
<MyInput label="Enter your name:" ref={ref} />
<button type="button" onClick={handleClick}>
Edit
</button>
</form>
);
}
ref를 과도하게 사용하지 마세요. 노드로 스크롤 하기, 노드에 포커스하기, 애니메이션 트리거하기, 텍스트 선택하기 등 prop로 표현할 수 없는 필수적인 동작에만 ref를 사용해야 합니다.
prop로 무언가를 표현할 수 있다면 ref를 사용해서는 안 됩니다. 예를 들어Modal
컴포넌트에서{ open, close }
와 같은 명령형 핸들을 노출하는 대신<Modal isOpen={isOpen} />
과 같이 propisOpen
을 사용하는 것이 더 좋습니다. Effects는 props를 통해 명령형 동작을 노출하는 데 도움이 될 수 있습니다.
https://ko.react.dev/reference/react/forwardRef#usage
현재 Input 컴포넌트를 만들 때 forwardRef를 사용해서 ref를 받아올 수 있는 Input으로 만들었다.
import { forwardRef } from 'react';
import { cn } from '@/utils/className';
export type InputProps = React.InputHTMLAttributes<HTMLInputElement>;
export const Input = forwardRef<HTMLInputElement, InputProps>(
({ className, type = 'text', ...props }, ref) => {
const inputClass = cn(
'w-full px-24 py-12 outline-none bg-white rounded-12 text-sm-normal md:text-base-normal',
className,
);
return <input ref={ref} type={type} className={inputClass} {...props} />;
},
);
Input.displayName = 'Input';
이때 Input.displayName을 지정해야하는 이유는
eslint-plugin-react 에서 Component definition is missing display name
에러를 내준다.
이 컴포넌트의 이름이 있어야하는데 export로만 반환하면 이름이 지정되어있지 않아서 나타내는 에러이다.
해결 방법
1. export default로 반환
2. displayName으로 이름 지정
React 공식문서 (한글)
https://ko.react.dev/reference/react/forwardRef#usage
Component definition is missing display name 에러
https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/display-name.md