Компоненты высшего порядка React: введение

Когда вы передаете компонент в функцию, она возвращает новый компонент – он называется компонентом высшего порядка. Звучит довольно просто, и на практике так оно и есть!

В этом руководстве вы увидите, как благодаря абстракции компонентов высшего порядка ваш код становится более читаемым, многоразовым и компонируемым.

Основные термины

Прежде чем двигаться дальше, давайте определим то, для чего мы создаем версию высшего порядка. Обратите внимание, многие из этих определений используются как взаимозаменяемые, однако об их различиях очень важно помнить:

  • Узел: HTML-элемент, смонтированный в DOM. Его можно отобразить при помощи браузера и изменять с помощью JavaScript.
  • Экземпляр: экземпляр класса компонента во время выполнения. Он представлен в памяти как объект JavaScript.
  • Элемент: фрагмент разметки, описывающий узел или потенциальный экземпляр. В React они передаются в объекты JavaScript, которые, в свою очередь, становятся экземплярами во время выполнения.
  • Компонент: абстракция над элементом. Они могут содержать какое-то внутреннее состояние и вести себя по-разному в зависимости от получаемых свойств. При запросе на рендеринг компоненты возвращают элементы.
  • Компонент высшего порядка (Higher Order Component, или HOC): абстракция над компонентом. При получении компонента (и, возможно, некоторых других параметров) они возвращают новый компонент.

Что такое компонент высшего порядка?

Допустим, мы собираемся начать работу над страницей User нашего приложения. Мы знаем, как выглядит объект User, но еще не совсем решили, какой тип авторизации хотим использовать. Можно ли избежать головной боли позже, когда мы определимся? Можно ли оставить себе возможность передумать через три месяца, когда страница уже готова? Да – благодаря компонентам высшего порядка.

Начнем с простой функции HOC по имени withUser. Мы хотим, чтобы эта функция охватывала все компоненты, которые мы ей передаем, и предоставляла объект User в качестве свойства:

const withUser = WrappedComponent => {
  class WithUser extends React.Component {
    constructor(props) {
      super(props);
      this.state = {
        user: sessionStorage.getItem("user")
      };
    }
    render() {
      return <^>{...this.props} />;
    }
  }

  return WithUser;
};<^>

Давайте разберемся с этим фрагментом:

  • Функция withUser принимает в качестве аргумента любой компонент.
  • Внутри мы создаем класс компонента WithUser, который считывает объект User из sessionStorage и добавляет его в состояние.
  • Функция рендеринга возвращает WrappedComponent как новый элемент со свойством из состояния.
  • Мы передаем внешний this.props внутреннему WrappedComponent.

Если вам не нужно состояние, в качестве альтернативы рекомендуется использовать функциональный HOC:

const withUser = WrappedComponent => {
  const user = sessionStorage.getItem("user");
  return props => ;
};

Компонент высшего порядка в работе

Если мы хотим получить доступ к объекту User на странице, мы можем вызвать withUser и обернуть в него компонент страницы:

const UserPage = props => (
  <div class="user-container">
    <p>My name is {props.user}!</p>
  </div>
);

export default withUser(UserPage);

Вот и все! Функция withUser принимает компонент в качестве аргумента и возвращает компонент высшего порядка. Что есть если через три месяца вы решите что-то изменить, вам нужно будет только отредактировать HOC.

Если вы раньше не были знакомы с компонентами высшего порядка, вы могли сталкиваться с ними, даже не осознавая этого. Вот некоторые примечательные примеры:

  • react-redux: connect(mapStateToProps, mapDispatchToProps)(UserPage)
  • react-router: withRouter(UserPage)
  • material-ui: withStyles(styles)(UserPage)

Функция compose

Функция compose из redux позволяет объединить несколько компонентов высшего порядка в один. Например:

import { compose } from 'redux';
// ... other imports

export default compose(
  withStyles(styles),
  withRouter,
  withUser
)(UserPage);

В этом случае стили, маршрутизатор и пользователь будут переданы компоненту UserPage.

Читайте также: Как использовать хуки React в Gatsby

Tags:

Добавить комментарий