useImperativeHandle là một React Hook cho phép bạn tùy chỉnh handle được hiển thị dưới dạng một ref.

useImperativeHandle(ref, createHandle, dependencies?)

Tham khảo

useImperativeHandle(ref, createHandle, dependencies?)

Gọi useImperativeHandle ở cấp cao nhất của component để tùy chỉnh ref handle mà nó hiển thị:

import { useImperativeHandle } from 'react';

function MyInput({ ref }) {
useImperativeHandle(ref, () => {
return {
// ... các phương thức của bạn ...
};
}, []);
// ...

Xem thêm các ví dụ bên dưới.

Tham số

  • ref: ref bạn nhận được như một prop cho component MyInput.

  • createHandle: Một hàm không nhận đối số và trả về ref handle bạn muốn hiển thị. Ref handle đó có thể có bất kỳ kiểu nào. Thông thường, bạn sẽ trả về một object với các phương thức bạn muốn hiển thị.

  • optional dependencies: Danh sách tất cả các giá trị reactive được tham chiếu bên trong code createHandle. Các giá trị reactive bao gồm props, state và tất cả các biến và hàm được khai báo trực tiếp bên trong phần thân component của bạn. Nếu linter của bạn được cấu hình cho React, nó sẽ xác minh rằng mọi giá trị reactive được chỉ định chính xác như một dependency. Danh sách các dependency phải có một số lượng mục không đổi và được viết nội dòng như [dep1, dep2, dep3]. React sẽ so sánh từng dependency với giá trị trước đó của nó bằng cách sử dụng so sánh Object.is. Nếu việc render lại dẫn đến thay đổi đối với một số dependency hoặc nếu bạn bỏ qua đối số này, hàm createHandle của bạn sẽ thực thi lại và handle mới được tạo sẽ được gán cho ref.

Note

Bắt đầu với React 19, ref có sẵn dưới dạng một prop. Trong React 18 trở về trước, cần phải lấy ref từ forwardRef.

Returns

useImperativeHandle trả về undefined.


Cách sử dụng

Hiển thị một ref handle tùy chỉnh cho component cha

Để hiển thị một DOM node cho phần tử cha, hãy truyền prop ref vào node đó.

function MyInput({ ref }) {
return <input ref={ref} />;
};

Với đoạn code trên, một ref đến MyInput sẽ nhận được DOM node <input>. Tuy nhiên, bạn có thể hiển thị một giá trị tùy chỉnh thay thế. Để tùy chỉnh handle được hiển thị, hãy gọi useImperativeHandle ở cấp cao nhất của component:

import { useImperativeHandle } from 'react';

function MyInput({ ref }) {
useImperativeHandle(ref, () => {
return {
// ... các phương thức của bạn ...
};
}, []);

return <input />;
};

Lưu ý rằng trong đoạn code trên, ref không còn được truyền cho <input>.

Ví dụ: giả sử bạn không muốn hiển thị toàn bộ DOM node <input>, nhưng bạn muốn hiển thị hai trong số các phương thức của nó: focusscrollIntoView. Để thực hiện việc này, hãy giữ DOM trình duyệt thực trong một ref riêng biệt. Sau đó, sử dụng useImperativeHandle để hiển thị một handle chỉ với các phương thức mà bạn muốn component cha gọi:

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

Bây giờ, nếu component cha nhận được một ref đến MyInput, nó sẽ có thể gọi các phương thức focusscrollIntoView trên đó. Tuy nhiên, nó sẽ không có toàn quyền truy cập vào DOM node <input> cơ bản.

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

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

  function handleClick() {
    ref.current.focus();
    // Thao tác này sẽ không hoạt động vì DOM node không được hiển thị:
    // ref.current.style.opacity = 0.5;
  }

  return (
    <form>
      <MyInput placeholder="Nhập tên của bạn" ref={ref} />
      <button type="button" onClick={handleClick}>
        Chỉnh sửa
      </button>
    </form>
  );
}


Hiển thị các phương thức imperative của riêng bạn

Các phương thức bạn hiển thị thông qua một imperative handle không nhất thiết phải khớp chính xác với các phương thức DOM. Ví dụ: component Post này hiển thị một phương thức scrollAndFocusAddComment thông qua một imperative handle. Điều này cho phép Page cha cuộn danh sách các comment focus vào trường input khi bạn nhấp vào nút:

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}>
        Viết một bình luận
      </button>
      <Post ref={postRef} />
    </>
  );
}

Chú Ý

Không nên lạm dụng refs. Bạn chỉ nên sử dụng refs cho các hành vi imperative mà bạn không thể thể hiện dưới dạng props: ví dụ: cuộn đến một node, focus một node, kích hoạt một animation, chọn văn bản, v.v.

Nếu bạn có thể thể hiện một cái gì đó dưới dạng một prop, bạn không nên sử dụng ref. Ví dụ: thay vì hiển thị một imperative handle như { open, close } từ một component Modal, tốt hơn là lấy isOpen làm một prop như <Modal isOpen={isOpen} />. Effects có thể giúp bạn hiển thị các hành vi imperative thông qua props.