[Hook] useImperativeHandle

OlMinJe·2025년 9월 2일

React

목록 보기
9/19

리액트 공식 문서를 참고한 정리 내용 (25.08 기준)

Ref로 노출되는 핸들을 사용자가 직접 정의할 수 있게 해주는 Hook이다.

useImperativeHandle(ref, createHandle, dependencies?)

컴포넌트의 최상위 레벨에서 useImperativeHandle을 호출하여 노출할 Ref 핸들을 사용자가 직접 정의할 수 있다.

import { useImperativeHandle } from 'react';

function MyInput({ ref }) {
  useImperativeHandle(ref, () => {
    return {
      // ... 메서드를 여기에 입력하세요 ...
    };
  }, []);
  // ...

매개변수

ref

  • 컴포넌트의 Props로 받은 ref이다.

createHandle

  • 인수가 없고 노출하려는 Ref 핸들을 반환하는 함수이다.
  • 해당 Ref 핸들은 어떠한 유형이든 될 수 있다.
  • 일반적으로 노출하려는 메서드가 있는 객체를 반환한다.

dependencies(선택적)

  • 코드 내에서 참조하는 모든 반응형 값을 나열한 목록이다.

👌🏻
React 19 부터 ref를 Prop으로 받을 수 있습니다. React 18 또는 그 이전 버전에서는 ref를 받기위해 forwardRef를 사용해야 한다고 하네용...


반환값

useImperativeHandleundefined를 반환한다.


사용법

부모 컴포넌트에 커스텀 Ref 핸들 노출

일반적인 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을 사용하면 부모에게 방 전체 대신 “빨래”만 주는 상황으로 비유할 수 있다. (필요한 것만 준다~)


사용자 정의 Imperative 메서드 노출

// 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>
    </>
  );
}
  • 꼭 DOM에 있는 focus() 같은 메서드만 노출할 필요 없음
  • 여러 동작을 묶은 새로운 메서드를 정의해서 부모에 전달할 수 있음

이렇게 하면 부모가 편하게 자식 기능을 제어할 수 있다

profile
큐트걸

0개의 댓글