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 menyesuaikan 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.

Parameter

  • 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 render ulang 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.

Kembalian

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>.

Sebagai contoh, jika Anda tidak ingin mengekspos keseluruhan DOM Node dari <input>, namun Anda ingin mengekspos dua method yang tersedia di dalamnya: focus dan scrollIntoView. Untuk melakukan hal tersebut, pertahankan DOM peramban yang asli ke dalam ref yang terpisah. Kemudian gunakan useImperativeHandle untuk mengekspos sebuah penanganan dengan methods yang Anda ingin panggil melalui komponen induk:

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} />;
});

Sekarang, jika komponen induk mendapatkan sebuah ref yang merujuk pada MyInput, komponen tersebut akan dapat memanggil method focus dan scrollIntoView. Meskipun begitu, komponen induk tersebut tidak akan memiliki akses penuh terhadap DOM Node <input> yang mendasarinya.

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>
  );
}


Mengekspos methods imperatif Anda sendiri

Methods yang diekspos melalui penanganan imperatif tidak harus sesuai dengan DOM Method secara persis. Sebagai contoh, komponen Post berikut mengekspos sebuah method scrollAndFocusAddComment melalui penanganan imperatif. Hal ini memungkinkan induk Page menggulir daftar komentar dan memfokuskan bidang input ketika Anda mengklik tombol:

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

Jangan terlalu sering menggunakan refs. Anda hanya boleh menggunakan refs untuk perilaku imperatif yang tidak dapat Anda ungkapkan sebagai props: misalnya, menggulir ke sebuah node, memfokuskan sebuah node, memicu sebuah animasi, memilih teks, dan sebagainya.

Jika Anda dapat mengekspresikan sesuatu sebagai prop, Anda tidak boleh menggunakan ref. Sebagai contoh, daripada mengekspos penanganan imperatif seperti { open, close } dari komponen Modal, lebih baik menggunakan isOpen sebagai prop seperti <Modal isOpen={isOpen} />. Effects dapat membantu Anda mengekspos perilaku imperatif melalui props.