Переадресация ссылок
Пересылка ссылок - это метод автоматической передачи ссылки через компонент одному из его дочерних элементов. Обычно это не требуется для большинства компонентов в приложении. Однако это может быть полезно для некоторых типов компонентов, особенно в библиотеках компонентов многократного использования. Наиболее распространенные сценарии описаны ниже.
Пересылка ссылок на компоненты DOM
Рассмотрим компонент FancyButton, который отображает элемент DOM встроенной кнопки:
function FancyButton(props) {
return (
<button className="FancyButton">
{props.children}
</button>
);
}
Компоненты React скрывают детали своей реализации, в том числе выводимые ими данные. Другие компоненты, использующие FancyButton, обычно не нуждаются в получении ссылки на внутренний элемент buttonDOM. Это хорошо, потому что не позволяет компонентам слишком полагаться на структуру DOM друг друга.
Хотя такая инкапсуляция желательна для компонентов уровня приложения, таких как FeedStory или Comment, она может быть неудобной для многократно используемых «листовых» компонентов, таких как FancyButton или MyTextInput. Эти компоненты, как правило, используются во всем приложении аналогично обычной кнопке DOM, и ввод и доступ к их узлам DOM могут быть неизбежны для управления фокусом, выбором или анимацией.
Переадресация ссылок является опциональной функцией, которая позволяет некоторым компонентам принимать ссылки, которые они получают, и передавать их дальше (другими словами, «пересылать») дочернему элементу.
В приведенном ниже примере FancyButton использует React.forwardRef для получения переданного ему ref, а затем перенаправляет его на кнопку DOM, которую он отображает:
const FancyButton = React.forwardRef((props, ref) => (
<button ref={ref} className="FancyButton">
{props.children}
</button>
));
// You can now get a ref directly to the DOM button:
const ref = React.createRef();
<FancyButton ref={ref}>Click me!</FancyButton>;
Таким образом, компоненты, использующие FancyButton, могут получить ссылку на базовый DOM-узел кнопки и получить к ней доступ при необходимости, как если бы они использовали кнопку DOM напрямую.
Вот пошаговое объяснение того, что происходит в приведенном выше примере:
- Мы создаем ссылку React, вызывая React.createRef и присваивая его переменной ref.
- Мы передаем наш реф до
указав его в качестве атрибута JSX. - React передает ref в функцию (props, ref) => ... внутри forwardRef в качестве второго аргумента.
- Мы передаем этот аргумент ref до <button ref = {ref}>, указав его в качестве атрибута JSX.
- Когда ссылка прикреплена, ref.current будет указывать на DOM-узел <button>.
Заметка
Второй аргумент ref существует только тогда, когда вы определяете компонент с помощью React.forwardRefcall. Компоненты обычной функции или класса не получают аргумента ref, и ссылка также недоступна в props.
Пересылка ссылок не ограничивается компонентами DOM. Вы также можете пересылать ссылки на экземпляры компонентов класса.
Примечание для сопровождающих библиотек компонентов
Когда вы начнете использовать forwardRef в библиотеке компонентов, вы должны рассматривать это как серьезное изменение и выпускать новую основную версию своей библиотеки. Это связано с тем, что ваша библиотека, вероятно, ведет себя по-разному (например, какие ссылки назначаются и какие типы экспортируются), и это может нарушить работу приложений и других библиотек, которые зависят от старого поведения.
Условное применение React.forwardRef, когда оно существует, также не рекомендуется по тем же причинам: оно меняет поведение вашей библиотеки и может нарушать работу приложений ваших пользователей при обновлении самого React.
Пересылка ссылок в компоненты высшего порядка
Этот метод также может быть особенно полезен для компонентов более высокого порядка (также известных как HOC). Давайте начнем с примера HOC, который регистрирует реквизиты компонентов на консоли:
function logProps(WrappedComponent) {
class LogProps extends React.Component {
componentDidUpdate(prevProps) {
console.log('old props:', prevProps);
console.log('new props:', this.props);
}
render() {
return <WrappedComponent {...this.props} />;
}
}
return LogProps;
}
HOC "logProps" передает все реквизиты компоненту, который оборачивает, поэтому выводимый результат будет таким же. Например, мы можем использовать этот HOC для регистрации всех реквизитов, которые передаются нашему компоненту «необычная кнопка»:
class FancyButton extends React.Component {
focus() {
// ...
}
// ...
}
// Rather than exporting FancyButton, we export LogProps.
// It will render a FancyButton though.
export default logProps(FancyButton);
В приведенном выше примере есть одна оговорка: ссылки не пройдут. Это потому что refis не опора. Как ключ, он обрабатывается по-разному в React. Если вы добавите ссылку на HOC, ссылка будет ссылаться на самый внешний компонент контейнера, а не на обернутый компонент.
Это означает, что ссылки, предназначенные для нашего компонента FancyButton, будут фактически присоединены к компоненту LogProps:
import FancyButton from './FancyButton';
const ref = React.createRef();
// The FancyButton component we imported is the LogProps HOC.
// Even though the rendered output will be the same,
// Our ref will point to LogProps instead of the inner FancyButton component!
// This means we can't call e.g. ref.current.focus()
<FancyButton
label="Click Me"
handleClick={handleClick}
ref={ref}
/>;
К счастью, мы можем явно пересылать ссылки на внутренний компонент FancyButton с помощью API React.forwardRef. React.forwardRef принимает функцию рендеринга, которая получает параметры props и ref и возвращает узел React. Например:
function logProps(Component) {
class LogProps extends React.Component {
componentDidUpdate(prevProps) {
console.log('old props:', prevProps);
console.log('new props:', this.props);
}
render() {
const {forwardedRef, ...rest} = this.props;
// Assign the custom prop "forwardedRef" as a ref
return <Component ref={forwardedRef} {...rest} />;
}
}
// Note the second param "ref" provided by React.forwardRef.
// We can pass it along to LogProps as a regular prop, e.g. "forwardedRef"
// And it can then be attached to the Component.
return React.forwardRef((props, ref) => {
return <LogProps {...props} forwardedRef={ref} />;
});
}
Новый контент: Composer: менеджер зависимостей для PHP , R программирования