Spec-Zone.ru › React 18

useImperativeHandle

useImperativeHandle — это React-хук, который позволяет настроить обработчик, экспонируемый как ссылка.

useImperativeHandle(ref, createHandle, dependencies?)
  • Ссылка
    • useImperativeHandle(ref, createHandle, dependencies?)
  • Использование
    • Экспонирование пользовательского обработчика ссылки родительскому компоненту
    • Экспонирование собственных императивных методов

Ссылка

useImperativeHandle(ref, createHandle, dependencies?)

Вызовите useImperativeHandle на верхнем уровне вашего компонента, чтобы настроить обработчик ссылки, который он экспонирует:

import { forwardRef, useImperativeHandle } from 'react';

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

См. дополнительные примеры ниже.

Параметры

  • ref: ref, полученный вами в качестве второго аргумента от forwardRef функции рендеринга.

  • createHandle: Функция без аргументов, которая возвращает обработчик ссылки, который вы хотите экспонировать. Этот обработчик ссылки может иметь любой тип. Обычно вы вернёте объект с методами, которые вы хотите экспонировать.

  • необязательно dependencies: Список всех реактивных значений, на которые ссылаются внутри кода createHandle. Реактивные значения включают свойства, состояние и все переменные и функции, объявленные непосредственно внутри тела вашего компонента. Если ваш линтер настроен для React, он проверит, что каждое реактивное значение правильно указано как зависимость. Список зависимостей должен содержать постоянное количество элементов и быть написан в строке, например [dep1, dep2, dep3]. React будет сравнивать каждую зависимость со своим предыдущим значением, используя Object.is сравнение. Если перерендеринг привёл к изменению какой-либо зависимости или вы опустили этот аргумент, ваша функция createHandle будет повторно выполнена, и созданный обработчик будет назначен ссылке.

Возвращаемое значение

useImperativeHandle возвращает undefined.


Использование

Экспонирование пользовательского обработчика ссылки родительскому компоненту

По умолчанию компоненты не экспонируют свои узлы DOM родительским компонентам. Например, если вы хотите, чтобы родительский компонент MyInput имел доступ к узлу DOM <input>, вы должны включить эту возможность с помощью forwardRef:

import { forwardRef } from 'react';

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

С приведенным выше кодом ссылка на MyInput получит узел DOM <input>. Однако вы можете экспонировать пользовательское значение вместо этого. Чтобы настроить экспонируемый обработчик, вызовите useImperativeHandle на верхнем уровне вашего компонента:

import { forwardRef, useImperativeHandle } from 'react';

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

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

Обратите внимание, что в приведенном выше коде ref больше не передаётся в <input>.

Например, предположим, что вы не хотите экспонировать весь узел DOM <input>, но хотите экспонировать два его метода: focus и scrollIntoView. Для этого сохраните реальный узел DOM браузера в отдельной ссылке. Затем используйте 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} />;
});

Теперь, если родительский компонент получит ссылку на 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();
    // This won't work because the DOM node isn't exposed:
    // 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} />
    </>
  );
}

Опасность

Не злоупотребляйте ссылками. Вы должны использовать ссылки только для императивных действий, которые нельзя выразить через свойства: например, для прокрутки к узлу, фокусировки на узле, запуска анимации, выбора текста и т. д.

Если вы можете выразить что-то через свойство, не используйте ссылку. Например, вместо экспонирования императивного обработчика, такого как { open, close } из компонента Modal, лучше передать isOpen в качестве свойства, как <Modal isOpen={isOpen} />. Эффекты могут помочь вам экспонировать императивные действия через свойства.

© 2013–present Facebook Inc.
Licensed under the Creative Commons Attribution 4.0 International Public License.
https://react.dev/reference/react/useImperativeHandle

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API