High Order Component (HOC)
High Order Component (hoc или «компонента высшего порядка») — это на самом деле не компонента, а функция, которая принимает компоненту и возвращает другую компоненту (контейнерную). Задача HOC принять однку компоненту, а вернуть другую для нее, наделенную какими-то способностями, которые повторяются для разных компонент в нашем коде.
Зачем нужны High Order Component?
High Order Component позволяет «клепать» однообразные контейнерные компоненты вокруг разных презентационных компонент либо других контейнерных. Благодаря этому удается избежать дублирования кода и лишней работы, по написанию этих дублей.
Напомним, что смыс контейнерной компоненты, как известно, снабдить презентационную компоненту какой-то «супер-способностью», а точнее выполнять за нее «грязное дело», например, отправлять асинхронный запрос, доставание из стейтов и пропсов, из url. То есть ее задача обеспечить презентационную компоненту необходимыми данными.
Как выглядят HOC?
Возвращать может функциональную либо классовую компоненту, зависимо от поставленной задачи.
Хоки принято называть с приставочкой with.
Как использовать?
Разберем на примере применения редиректа для незалогиненых пользователей на некоторых страницах.
- Создаем в папке components папку hoc. А внутри файл withAuthRedirect.js со следующим содержаниям:
import React from 'react'; import {Redirect} from 'react-router-dom'; import { connect } from 'react-redux'; let mapStateToPropsForRedirect = (state) => ({ isAuth: state.auth.isAuth }); export const withAuthRedirect = (Component) => { class RedirectComponent extends React.Component { render() { if (!this.props.isAuth) return <Redirect to='/login' /> return <Component {...this.props} /> } } let ConectedAuthRedirectComponent = connect(mapStateToPropsForRedirect) (RedirectComponent); return ConectedAuthRedirectComponent; }
Здесь происходит оборачивание принимаемой компоненты (Component) в новую — withAuthRedirect. Затем еще происходит необязательное оборачивание ее в ConectedAuthRedirectComponent, чтобы законектить mapStateToPropsForRedirect для проверки, является ли пользователь авторизованым. Это можно было сделать и в файле, где применяется сам HOC, но тогда тоже происходило бы в каждом файле дублирование кода для этой проверки.
- Теперь в файлах контейнерных компонет мы можем вызов презентационной компоненты мы можем передать в этот созданный ранее HOC, а потом законектить уже не презентационную компоненту, а новую созданную. Вот так (это последние 3 строчки кода DialogsContainer.jsx):
let AuthRedirectComponent = withAuthRedirect(Dialogs); const DialogsContainer = connect(mapStateToProps, mapDispatchToProps) (AuthRedirectComponent); export default DialogsContainer;
- Но правильнее теперь эти 3 строчки переписать через Compose. Вот так:
export default compose( connect(mapStateToProps, mapDispatchToProps), withAuthRedirect )(Dialogs);