forwardRef를 걷어내도 되는 이유 — ref가 그냥 prop이 됐습니다
문제 발생
디자인 시스템의 Input처럼 DOM 요소를 감싸는 컴포넌트는 바깥에서 포커스를 주려면 ref를 통과시켜야 했고, 그 때문에 전부 forwardRef로 감싸야 했습니다.
const MyInput = forwardRef(function MyInput({ placeholder }, ref) {
return <input placeholder={placeholder} ref={ref} />;
});컴포넌트 하나마다 래퍼가 한 겹씩 늘고, displayName을 따로 지정해야 하며, ref를 두 개 이상 내려보내야 할 때는 방법이 없었습니다.
원인 분석
ref는 오랫동안 key와 함께 prop이 아닌 특별한 값이었습니다. JSX에 ref를 적어도 컴포넌트의 props에는 들어오지 않았고, 그래서 별도 통로인 forwardRef가 필요했습니다.
React 19에서 이 예외가 없어졌습니다. 함수 컴포넌트에서 ref는 그냥 props의 한 항목입니다.
새로 만드는 함수 컴포넌트는 더 이상
forwardRef가 필요 없고, 앞으로의 버전에서forwardRef는 deprecated 후 제거될 예정입니다.
해결 방안
- 래퍼를 벗기고 props에서 꺼내 씁니다.
function MyInput({ placeholder, ref }) {
return <input placeholder={placeholder} ref={ref} />;
}
<MyInput ref={inputRef} placeholder="이름" />- ref를 여러 개 내려보낼 수 있습니다. 이름이 자유로우니 특별 취급받는
ref외에 추가 참조를 얼마든지 정의할 수 있습니다.
function Field({ inputRef, labelRef, label }) {
return (
<>
<label ref={labelRef}>{label}</label>
<input ref={inputRef} />
</>
);
}- 클래스 컴포넌트에는 해당되지 않습니다. 이 변경은 함수 컴포넌트 이야기입니다.
- 한 번에 다 바꾸지 않아도 됩니다.
forwardRef는 19에서도 그대로 동작하므로, 새로 만드는 컴포넌트부터 적용하고 기존 것은 공식 codemod로 정리하면 됩니다. - 타입을 함께 정리합니다. TypeScript에서는
forwardRef의 제네릭 두 개 대신 props 인터페이스에ref를 넣으면 되므로 시그니처가 눈에 띄게 짧아집니다.
interface MyInputProps {
placeholder?: string;
ref?: React.Ref<HTMLInputElement>;
}
댓글0
댓글을 남기려면 로그인이 필요해요. 로그인
아직 댓글이 없어요. 첫 의견을 편하게 남겨 보세요.