useImperativeHandle

useImperativeHandle adalah sebuah React Hook yang memungkinkan Anda menyesuaikan penanganan yang diekspos sebagai ref.

useImperativeHandle(ref, createHandle, dependencies?)

Referensi

useImperativeHandle(ref, createHandle, dependencies?)

Panggil fungsi useImperativeHandle di tingkat atas komponen Anda untuk mengkustomisasi penanganan yang diekspos oleh ref:

import { forwardRef, useImperativeHandle } from 'react';

const MyInput = forwardRef(function MyInput(props, ref) {
useImperativeHandle(ref, () => {
return {
// ... your methods ...
};
}, []);
// ...

See more examples below.

Parameters

  • ref: ref yang Anda terima sebagai argumen ke-dua dari fungsi render forwardRef.

  • createHandle: Sebuah fungsi yang tidak mengambil argumen dan mengembalikan penanganan ref yang ingin Anda ekspos. Penanganan ref tersebut dapat memiliki tipe any. Biasanya, Anda akan mengembalikan sebuah object dengan sekumpulan metode yang ingin Anda ekspos.

  • opsional dependencies: Daftar semua nilai reaktif yang dirujuk di dalam kode setup. Nilai reaktif termasuk props, state, dan semua variabel dan fungsi yang dideklarasikan langsung di dalam komponen. Jika linter Anda telah dikonfigurasi untuk React, maka linter tersebut akan memverifikasi bahwa setiap nilai reaktif sudah diatur dengan benar sebagai dependensi. Daftar dependensi ini harus memiliki jumlah item yang konstan dan ditulis secara inline seperti [dep1, dep2, dep3]. React akan membandingkan setiap dependensi dengan nilai lama menggunakan perbandingan Object.is. Jika sebuah re-render menghasilkan sebuah perubahan terhadap beberapa dependency, atau jika Anda menghilangkan argumen ini, fungsi createHandle Anda akan dijalankan ulang, dan penanganan yang baru dibuat akan ditempatkan ke ref.

Returns

useImperativeHandle mengembalikan undefined.


Penggunaan

Mengekspos sebuah penanganan ref kustom kepada komponen induk

Secara bawaan, komponen tidak mengekspos DOM nodes kepada komponen induk. Sebagai contoh, jika Anda menginginkan komponen induk dari MyInput untuk memiliki akses terhadap DOM node dari <input>, Anda harus menyertakannya dengan forwardRef:

import { forwardRef } from 'react';

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

Dengan kode di atas, sebuah ref yang diteruskan ke komponen MyInput akan menerima DOM node dari <input>. Namun, Anda dapat mengekspos sebuah nilai kustom. Untuk mengkustom penanganan yang diekspos, panggil fungsi useImperativeHandle di tingkat atas komponen Anda:

import { forwardRef, useImperativeHandle } from 'react';

const MyInput = forwardRef(function MyInput(props, ref) {
useImperativeHandle(ref, () => {
return {
// ... your methods ...
};
}, []);

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

Perlu dicatat bahwa dalam kode di atas, ref tidak lagi diteruskan kepada <input>.

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:

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.

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:
    // ref.current.style.opacity = 0.5;
  }

  return (
    <form>
      <MyInput label="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:

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.

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.