리액트 공식 문서를 참고한 정리 내용 (25.08 기준)
Ref로 노출되는 핸들을 사용자가 직접 정의할 수 있게 해주는 Hook이다.
useImperativeHandle(ref, createHandle, dependencies?)
컴포넌트의 최상위 레벨에서 useImperativeHandle을 호출하여 노출할 Ref 핸들을 사용자가 직접 정의할 수 있다.
import { useImperativeHandle } from 'react';
function MyInput({ ref }) {
useImperativeHandle(ref, () => {
return {
// ... 메서드를 여기에 입력하세요 ...
};
}, []);
// ...
refref이다. createHandledependencies(선택적)👌🏻
React 19 부터ref를 Prop으로 받을 수 있습니다. React 18 또는 그 이전 버전에서는ref를 받기위해forwardRef를 사용해야 한다고 하네용...
useImperativeHandle은 undefined를 반환한다.
일반적인 Ref 동작은 아래와 같다.
function MyInput({ ref }) {
return <input ref={ref} />;
}
ref를 전달하면 → 부모는 <input> DOM 노드 전체를 바로 조작할 수 있다.inputRef.current.value, inputRef.current.focus() 등 <input> DOM API 전체 접근 가능.👉 하지만 가끔은 DOM 전체를 열어주지 않고, 특정 기능만 제공하고 싶을 때가 있어서((이벤트 조작 등) 해당 useImperativeHandle이 등장했다.
import { useRef, useImperativeHandle } from 'react';
function MyInput({ ref }) {
const inputRef = useRef(null);
useImperativeHandle(ref, () => {
return {
focus() {
inputRef.current.focus();
},
scrollIntoView() {
inputRef.current.scrollIntoView();
},
};
}, []);
return <input ref={inputRef} />;
}
inputRef는 실제 <input> DOM을 가리킴 (내부적으로만 사용)useImperativeHandle(ref, () => {...}) → 부모에게는 focus, scrollIntoView 두 메서드만 노출myInputRef.current에 접근할 때는 DOM 전체가 아니라 이 메서드들만 사용 가능그러면 부모에서는 어떻게 사용하는가?
function Parent() {
const myInputRef = useRef(null);
return (
<>
<MyInput ref={myInputRef} />
<button onClick={() => myInputRef.current.focus()}>
Focus Input
</button>
<button onClick={() => myInputRef.current.scrollIntoView()}>
Scroll Input
</button>
</>
);
}
Ref만 전달했을 때는 부모가 자식 방에 들어가서 모든 물건을 건드리지만, useImperativeHandle을 사용하면 부모에게 방 전체 대신 “빨래”만 주는 상황으로 비유할 수 있다. (필요한 것만 준다~)
// child
function Post({ ref }) {
const listRef = useRef(null);
const inputRef = useRef(null);
useImperativeHandle(ref, () => ({
scrollAndFocusAddComment() {
// 댓글 목록을 스크롤 맨 아래로 이동
listRef.current.scrollIntoView();
// 입력창에 포커스 주기
inputRef.current.focus();
}
}));
return (
<>
<div ref={listRef}>댓글 목록...</div>
<input ref={inputRef} placeholder="댓글 입력" />
</>
);
}
// parent
function Page() {
const postRef = useRef(null);
return (
<>
<Post ref={postRef} />
<button onClick={() => postRef.current.scrollAndFocusAddComment()}>
댓글 달러 가기
</button>
</>
);
}
focus() 같은 메서드만 노출할 필요 없음이렇게 하면 부모가 편하게 자식 기능을 제어할 수 있다