useImperativeHandle
useImperativeHandle
це хук, який дозволяє кастомізувати об’єкт, який повертається через реф.
useImperativeHandle(ref, createHandle, dependencies?)
Опис
useImperativeHandle(ref, createHandle, dependencies?)
Викличте useImperativeHandle
на верхньому рівні вашого компонента, щоб кастомізувати об’єкт посилання, який повертає реф:
import { useImperativeHandle } from 'react';
function MyInput({ ref }) {
useImperativeHandle(ref, () => {
return {
// ... ваші методи ...
};
}, []);
// ...
Перегляньте більше прикладів нижче.
Параметри
-
ref
:Реф
, який ви отримали як проп у компонентіMyInput
. -
createHandle
: Функція, яка не приймає аргументів і повертає об’єкт посилання, який ви хочете надати. Цей об’єкт може бути будь-якого типу. Зазвичай, ви повертатимете об’єкт з методами, які ви захочете використовувати. -
Опціональний параметр
dependencies
: Список усіх реактивних значень, на які посилається кодcreateHandle
. Реактивні значення включають в себе пропси, стан та всі змінні та функції, оголошені безпосередньо в тілі компонента. Якщо ваш лінтер налаштований для Реакту, він перевірить, чи кожне реактивне значення вказане як залежність. Список залежностей повинен містити стале число елементів, записаних в рядок як[залежність1, залежність2, залежність3]
. Реакт порівняє кожну залежність із своїм попереднім значенням використовуючи порівнянняObject.is
. Якщо повторний рендер призвів до зміни однієї із залежностей або якщо ви пропустили даний аргумент, вашаcreateHandle
функція буде виконана повторно і новостворений об’єкт посилання буде призначений до рефу.
Результат
useImperativeHandle
повертає undefined
.
Використання
Надання кастомного об’єкта посилання батьківському компоненту
Щоб надати DOM-вузол батьківському елементу, передайте проп ref до цього вузла.
function MyInput({ ref }) {
return <input ref={ref} />;
};
У коді вище посилання до MyInput
отримає DOM вузол <input>
. Однак, замість цього ви можете передати кастомне значення. Щоб кастомізувати наданий об’єкт посилання, викличте useImperativeHandle
на верхньому рівні вашого компонента:
import { useImperativeHandle } from 'react';
function MyInput({ ref }) {
useImperativeHandle(ref, () => {
return {
// ... ваші методи ...
};
}, []);
return <input />;
};
Зверніть увагу, що в наданому вище коді реф
більше не передається до <input>
.
Наприклад, припустимо, ви не хочете використовувати весь вузол DOM <input>
, а лише два його методи: focus
і scrollIntoView
. Щоб зробити це, зберігайте справжній браузерний 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} />;
};
Тепер, якщо батьківський компонент передасть реф до MyInput
, він буде здатний викликати методи focus
і scrollIntoView
в компоненті. Однак, він не буде мати повного доступу до DOM вузла <input>
.
import { useRef } from 'react'; import MyInput from './MyInput.js'; export default function Form() { const ref = useRef(null); function handleClick() { ref.current.focus(); // Це не спрацює, бо вузол DOM не був представлений: // ref.current.style.opacity = 0.5; } return ( <form> <MyInput placeholder="Enter your name" ref={ref} /> <button type="button" onClick={handleClick}> Edit </button> </form> ); }
Передавання власних імперативних методів
Методи, які ви передаєте через імперативний обробник не обов’язково мають точно відповідати 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} /> </> ); }