useImperativeHandle

useImperativeHandle is a React Hook that lets you customize the handle exposed as a ref. useImperativeHandleref로 노출되는 핸들을 사용자가 직접 정의할 수 있게 해주는 React 훅입니다.

useImperativeHandle(ref, createHandle, dependencies?)

Reference참조

useImperativeHandle(ref, createHandle, dependencies?)

Call useImperativeHandle at the top level of your component to customize the ref handle it exposes: 컴포넌트의 최상위 레벨에서 useImperativeHandle을 호출하여 노출할 ref 핸들을 사용자가 직접 정의할 수 있습니다:

import { forwardRef, useImperativeHandle } from 'react';

const MyInput = forwardRef(function MyInput(props, ref) {
useImperativeHandle(ref, () => {
return {
// ... your methods ...
// ... 메서드는 여기에 작성합니다 ...
};
}, []);
// ...

See more examples below. 아래에서 더 많은 예시를 확인하세요.

Parameters매개변수

  • ref: The ref you received as the second argument from the forwardRef render function. ref: forwardRef 렌더 함수에서 두 번째 인자로 받은 ref입니다.

  • createHandle: A function that takes no arguments and returns the ref handle you want to expose. That ref handle can have any type. Usually, you will return an object with the methods you want to expose. createHandle: 인자가 없고 노출하려는 ref 핸들을 반환하는 함수입니다. 해당 ref 핸들은 어떠한 유형이든 될 수 있습니다. 일반적으로 노출하려는 메서드가 있는 객체를 반환합니다.

  • optional dependencies: The list of all reactive values referenced inside of the createHandle code. Reactive values include props, state, and all the variables and functions declared directly inside your component body. If your linter is configured for React, it will verify that every reactive value is correctly specified as a dependency. The list of dependencies must have a constant number of items and be written inline like [dep1, dep2, dep3]. React will compare each dependency with its previous value using the Object.is comparison. If a re-render resulted in a change to some dependency, or if you omitted this argument, your createHandle function will re-execute, and the newly created handle will be assigned to the ref. (선택적) dependencies: createHandle 코드 내에서 참조하는 모든 반응형 값을 나열한 목록입니다. 반응형 값은 props, state 및 컴포넌트 내에서 직접 선언한 모든 변수와 함수를 포함합니다. React에 대한 린터를 구성한 경우 모든 반응형 값이 올바르게 의존성으로 지정되었는지 확인합니다. 의존성 목록은 항상 일정한 수의 항목을 가지고 [dep1, dep2, dep3]와 같이 인라인으로 작성되어야 합니다. React는 각 의존성을 Object.is 비교를 사용하여 이전 값과 비교합니다. 리렌더링으로 인해 일부 의존성이 변경되거나 이 인수를 생략한 경우, createHandle 함수가 다시 실행되고 새로 생성된 핸들이 ref에 할당됩니다.

Returns반환값

useImperativeHandle returns undefined. useImperativeHandle은 undefined를 반환합니다.


Usage사용법

Exposing a custom ref handle to the parent component 부모 컴포넌트에 커스텀 ref 핸들 노출

By default, components don’t expose their DOM nodes to parent components. For example, if you want the parent component of MyInput to have access to the <input> DOM node, you have to opt in with forwardRef: 기본적으로 컴포넌트는 자식 컴포넌트의 DOM 노드를 부모 컴포넌트에 노출하지 않습니다. 예를 들어, MyInput의 부모 컴포넌트가 <input> DOM 노드에 접근하려면 forwardRef를 사용하여 선택적으로 참조에 포함해야 합니다:

import { forwardRef } from 'react';

const MyInput = forwardRef(function MyInput(props, ref) {
return <input {...props} ref={ref} />;
});

With the code above, a ref to MyInput will receive the <input> DOM node. However, you can expose a custom value instead. To customize the exposed handle, call useImperativeHandle at the top level of your component: 위의 코드에서 MyInput에 대한 ref는 <input> DOM 노드를 받게 됩니다. 그러나 대신 사용자 지정 값을 노출할 수 있습니다. 노출된 핸들을 사용자 정의하려면 컴포넌트의 최상위 레벨에서 useImperativeHandle을 호출하세요.

import { forwardRef, useImperativeHandle } from 'react';

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

return <input {...props} />;
});

Note that in the code above, the ref is no longer forwarded to the <input>. 위의 코드에서 <input>에 대한 ref는 더 이상 전달되지 않습니다.

For example, suppose you don’t want to expose the entire <input> DOM node, but you want to expose two of its methods: focus and scrollIntoView. To do this, keep the real browser DOM in a separate ref. Then use useImperativeHandle to expose a handle with only the methods that you want the parent component to call: 예를 들어, 전체 <input> DOM 노드를 노출하지 않고 focusscrollIntoView의 두 메서드만을 노출하고 싶다고 가정해 봅시다. 그러기 위해서는 실제 브라우저 DOM을 별도의 ref에 유지해야 합니다. 그리고 useImperativeHandle을 사용하여 부모 컴포넌트에서 호출할 메서드만 있는 핸들을 노출합니다:

import { forwardRef, useRef, useImperativeHandle } from 'react';

const MyInput = forwardRef(function MyInput(props, ref) {
const inputRef = useRef(null);

useImperativeHandle(ref, () => {
return {
focus() {
inputRef.current.focus();
},
scrollIntoView() {
inputRef.current.scrollIntoView();
},
};
}, []);

return <input {...props} ref={inputRef} />;
});

Now, if the parent component gets a ref to MyInput, it will be able to call the focus and scrollIntoView methods on it. However, it will not have full access to the underlying <input> DOM node. 이제 부모 컴포넌트가 MyInput에 대한 ref를 가져오면 focusscrollIntoView 메서드를 호출할 수 있습니다. 그러나 기본 <input> DOM 노드의 전체 액세스 권한은 없습니다.

import { useRef } from 'react';
import MyInput from './MyInput.js';

export default function Form() {
  const ref = useRef(null);

  function handleClick() {
    ref.current.focus();
    // This won't work because the DOM node isn't exposed:
    // 이 작업은 DOM 노드가 노출되지 않으므로 작동하지 않습니다.
    // ref.current.style.opacity = 0.5;
  }

  return (
    <form>
      <MyInput placeholder="Enter your name" ref={ref} />
      <button type="button" onClick={handleClick}>
        Edit
      </button>
    </form>
  );
}


Exposing your own imperative methods 사용자 정의 명령 노출

The methods you expose via an imperative handle don’t have to match the DOM methods exactly. For example, this Post component exposes a scrollAndFocusAddComment method via an imperative handle. This lets the parent Page scroll the list of comments and focus the input field when you click the button: imperative handle을 통해 노출하는 메서드는 DOM 메서드와 정확하게 일치할 필요가 없습니다. 예를 들어, 이 Post 컴포넌트는 명령 핸들을 통해 ScrollAndFocusAddComment 메서드를 표시합니다. 이렇게 하면 부모 Page에서 버튼을 클릭할 때 댓글 목록을 스크롤하고 입력 필드에 초점을 맞출 수 있습니다.

import { useRef } from 'react';
import Post from './Post.js';

export default function Page() {
  const postRef = useRef(null);

  function handleClick() {
    postRef.current.scrollAndFocusAddComment();
  }

  return (
    <>
      <button onClick={handleClick}>
        Write a comment
      </button>
      <Post ref={postRef} />
    </>
  );
}

Pitfall | 함정

Do not overuse refs. You should only use refs for imperative behaviors that you can’t express as props: for example, scrolling to a node, focusing a node, triggering an animation, selecting text, and so on. ref를 과도하게 사용하지 마세요. ref는 props로 표현할 수 없는 필수적인 행동에만 사용해야 합니다. 예를 들어, 특정 노드로 스크롤하기, 노드에 초점 맞추기, 애니메이션 촉발하기, 텍스트 선택하기 등이 있습니다.

If you can express something as a prop, you should not use a ref. For example, instead of exposing an imperative handle like { open, close } from a Modal component, it is better to take isOpen as a prop like <Modal isOpen={isOpen} />. Effects can help you expose imperative behaviors via props. prop으로 표현할 수 있는 것은 ref를 사용하지 마세요. 예를 들어, Modal 컴포넌트에서 {open, close}와 같은 imperative handle을 노출하는 대신 <Modal isOpen={isOpen} />과 같은 isOpen prop을 사용하는 것이 더 좋습니다. Effect를 사용하면 prop을 통해 명령형 동작(imperative behavior)을 노출할 수 있습니다.