что такое hoc в react

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

Nov 17, 2019 · 4 min read

В этой статье мы рассмотрим компоненты высшего порядка (Higher-Order Components, HOC) в React.

Что такое HOC?

HOC — это особая техника в React, при которой функция принимает аргумент Component и возвращает новый компонент.

В данном примере функция composeComponent принимает аргумент Component и возвращает компонент ES6 class. Возвращенный класс отображает аргумент Component. Аргумент Component является компонентом React, который будет отображаться возвращенным компонентом class.

CatComponent отображает следующее:

CatComponet может быть передан функции composeComponent для получения другого компонента:

composedCatComponent может быть отображен:

Результат выглядит следующим образом:

Та же функция высшего порядка, как и в JS.

Функция высшего порядка

Функция вы с шего порядка — это шаблон в JS, при котором одна функция принимает другую функцию и возвращает функцию в качестве результата, что является возможным благодаря композиционному характеру JS. Это означает, что:

могут быть переданы функциям в качестве аргументов или возвращены из функции.

Функция mul возвращает функцию, которая захватывает x в замыкании. x теперь доступен для возвращенной функции, а mul является теперь функцией высшего порядка, поскольку она возвращает функцию. Это означает, что ее можно использовать для создания более специфических функций с использованием различных аргументов.

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

В чем преимущества элементов высшего порядка? При постоянном повторении логики нужно найти способ разместить логику в одном месте и использовать ее оттуда. Функции высшего порядка предоставляют шаблон, который можно использовать для этой реализации.

Общие проблемы при работе с HOC

В чем преимущества использования HOC в приложении React?

В процессе написания программы одна и та же логика может повторяться снова и снова.

Например, приложение для просмотра и редактирования документов. Приложение будет аутентифицировано, поэтому только аутентифицированные пользователи смогут получить доступ к панели инструментов, редактировать, просматривать или удалять документы. Маршруты будут выглядеть следующим образом:

Документы нужно аутентифицировать, чтобы только аутентифицированные пользователи могли получить к ним доступ. Для этого необходимо сделать следующее:

State.auth содержит состояние пользователя. Если пользователь не аутентифицирован, то значение будет false, в обратно случае — true. Функция connect отобразит состояние для объектов props isAuth. Затем при подключении компонента к DOM запускается componentWillMount. Здесь нужно проверить, обладает ли prop isAuth значением true. При значении true метод передается вниз, а при значении false метод передает маршрут “/” индексной страницы маршрутизатору. В результате браузер загружает страницу индекса внутри рендеринга компонента documents, запрещая не аутентифицированным пользователям получить доступ.

Когда компонент выполняет ре-рендеринг после первоначального рендеринга, необходимо выполнить те же действия в componentWillUpdate, чтобы проверить, авторизован ли пользователь. Если нет, загружается страница индекса.

Теперь сделаем то же самое в ViewDocument:

Также в DelDocument:

Страницы выполняют различные действия, однако реализация одинакова.

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

Поэтому нужно найти способ для определения логики в одном месте. Лучше всего использовать HOC.

Для этого перемещаем всю логику в функцию, которая будет возвращать компонент:

Все реализации находятся внутри компонента Authentication. Функция requireAuthentication соединяет компонент Authentication с хранилищем и возвращает его. Затем Authentication отображает компонент, переданный через аргумент ComposedCompoennt.

Маршруты теперь выглядят следующим образом:

Таким образом, независимо от количества маршрутов в приложении, нужно просто вызвать функцию requireAuthentication с переданным ей компонентом.

Заключение

Функция высшего порядка:

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

Источник

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

В этой статье мы рассмотрим компоненты высшего порядка (Higher-Order Components, HOC) в React.

Что такое HOC?

HOC — это особая техника в React, при которой функция принимает аргумент Component и возвращает новый компонент.

В данном примере функция composeComponent принимает аргумент Component и возвращает компонент ES6 class. Возвращенный класс отображает аргумент Component. Аргумент Component является компонентом React, который будет отображаться возвращенным компонентом class.

CatComponent отображает следующее:

CatComponet может быть передан функции composeComponent для получения другого компонента:

composedCatComponent может быть отображен:

Результат выглядит следующим образом:

Та же функция высшего порядка, как и в JS.

Функция высшего порядка

Функция высшего порядка — это шаблон в JS, при котором одна функция принимает другую функцию и возвращает функцию в качестве результата, что является возможным благодаря композиционному характеру JS. Это означает, что:

могут быть переданы функциям в качестве аргументов или возвращены из функции.

Функция mul возвращает функцию, которая захватывает x в замыкании. x теперь доступен для возвращенной функции, а mul является теперь функцией высшего порядка, поскольку она возвращает функцию. Это означает, что ее можно использовать для создания более специфических функций с использованием различных аргументов.

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

В чем преимущества элементов высшего порядка? При постоянном повторении логики нужно найти способ разместить логику в одном месте и использовать ее оттуда. Функции высшего порядка предоставляют шаблон, который можно использовать для этой реализации.

Общие проблемы при работе с HOC

В чем преимущества использования HOC в приложении React?

В процессе написания программы одна и та же логика может повторяться снова и снова.

Например, приложение для просмотра и редактирования документов. Приложение будет аутентифицировано, поэтому только аутентифицированные пользователи смогут получить доступ к панели инструментов, редактировать, просматривать или удалять документы. Маршруты будут выглядеть следующим образом:

Документы нужно аутентифицировать, чтобы только аутентифицированные пользователи могли получить к ним доступ. Для этого необходимо сделать следующее:

State.auth содержит состояние пользователя. Если пользователь не аутентифицирован, то значение будет false, в обратно случае — true. Функция connect отобразит состояние для объектов props isAuth. Затем при подключении компонента к DOM запускается componentWillMount. Здесь нужно проверить, обладает ли prop isAuth значением true. При значении true метод передается вниз, а при значении false метод передает маршрут “/” индексной страницы маршрутизатору. В результате браузер загружает страницу индекса внутри рендеринга компонента documents, запрещая не аутентифицированным пользователям получить доступ.

Читайте также:  что делают инженерные войска в российской армии

Когда компонент выполняет ре-рендеринг после первоначального рендеринга, необходимо выполнить те же действия в componentWillUpdate, чтобы проверить, авторизован ли пользователь. Если нет, загружается страница индекса.

Теперь сделаем то же самое в ViewDocument:

Также в DelDocument:

Страницы выполняют различные действия, однако реализация одинакова.

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

Поэтому нужно найти способ для определения логики в одном месте. Лучше всего использовать HOC.

Для этого перемещаем всю логику в функцию, которая будет возвращать компонент:

Все реализации находятся внутри компонента Authentication. Функция requireAuthentication соединяет компонент Authentication с хранилищем и возвращает его. Затем Authentication отображает компонент, переданный через аргумент ComposedCompoennt.

Маршруты теперь выглядят следующим образом:

Таким образом, независимо от количества маршрутов в приложении, нужно просто вызвать функцию requireAuthentication с переданным ей компонентом.

Заключение

Функция высшего порядка:

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

Источник

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

Недавно мы публиковали материал о функциях высшего порядка в JavaScript, направленный на тех, кто изучает JavaScript. Статья, перевод которой мы публикуем сегодня, предназначена для начинающих React-разработчиков. Она посвящена компонентам высшего порядка (Higher-Order Components, HOC).

Принцип DRY и компоненты высшего порядка в React

Вам не удастся достаточно далеко продвинуться в деле изучения программирования и не столкнуться с почти что культовым принципом DRY (Don’t Repeat Yourself, не повторяйтесь). Иногда его последователи заходят даже слишком далеко, но, в большинстве случаев, к его соблюдению стоит стремиться. Здесь мы поговорим о самом популярном паттерне React-разработки, позволяющем обеспечить соблюдение принципа DRY. Речь идёт о компонентах высшего порядка. Для того чтобы понять ценность компонентов высшего порядка, давайте сначала сформулируем и поймём проблему, для решения которой они предназначены.

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


Панель управления и всплывающие подсказки

Теперь всё готово. Возможно, вы уже писали что-то подобное на React. Это, конечно, не самый плохой код в мире, но он не особенно хорошо следует принципу DRY. Как можно видеть, проанализировав код компонентов, мы, в каждом из них, повторяем одну и ту же логику.

Проблема, которая перед нами стоит, сейчас должна стать предельно ясной. Это — повторяющийся код. Для её решения мы хотим избавиться от необходимости копирования одного и того же кода в тех случаях, когда то, что мы уже реализовали, нужно новому компоненту. Как же её решить? Прежде чем мы об этом поговорим, остановимся на нескольких концепциях программирования, которые значительно облегчат понимание предлагаемого здесь решения. Речь идёт о коллбэках и функциях высшего порядка.

Функции высшего порядка

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

Если вы к такому поведению не привыкли, то вышеприведённый код может показаться вам странным. Поговорим о том, что здесь происходит. А именно, мы передаём функцию add функции addFive в виде аргумента, переименовываем её в addReference и после этого вызываем.

Когда пользуются подобными конструкциями, функция, переданная другой в виде аргумента, называется коллбэком (функцией обратного вызова), а функция, которая получает другую функцию в виде аргумента, называется функцией высшего порядка.

Именование сущностей в программировании — это важно, поэтому вот тот же самый код, используемые в котором имена изменены сообразно тем концепциям, которые они представляют.

Этот паттерн должен показаться вам знакомым. Дело в том, что если вы пользовались, например, методами массивов JavaScript, работали с jQuery или с lodash, то вы уже использовали и функции высшего порядка и коллбэки.

Взглянем на пример реализации вышеописанных механизмов.

Всё это хорошо, но при чём тут React и вышеописанная проблема дублирования кода обработки событий мыши при создании новых компонентов, которым нужна эта возможность? Дело в том, что точно так же, как функция высшего порядка makeAdder помогает нам минимизировать дублирование кода, то, что называется «компонент высшего порядка», поможет нам справиться с той же проблемой в React-приложении. Однако тут всё будет выглядеть несколько иначе. А именно, вместо схемы работы, в ходе которой функция высшего порядка возвращает новую функцию, которая вызывает коллбэк, компонент высшего порядка может реализовать собственную схему. А именно, он способен возвратить новый компонент, который рендерит компонент, играющий роль «коллбэка». Пожалуй, мы уже очень много всего наговорили, поэтому пора перейти к примерам.

Наша функция высшего порядка

Эта функция отличается следующими особенностями:

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

Этот компонент можно охарактеризовать так:

Внедрение HOC

Теперь, когда мы, в общих чертах, разобрались с тем, какие именно действия выполняет компонент высшего порядка, начнём вносить изменения в наш React-код. Если помните, суть решаемой нами проблемы заключается в том, что код, реализующий логику обработки событий мыши, приходится копировать во все компоненты, которым нужна эта возможность.

▍Приём аргумента Component

▍Возврат нового компонента

▍Рендеринг компонента Component с передачей ему свойства hovering

Дополнительные замечания

К этому моменту мы рассмотрели все базовые сведения о компонентах высшего порядка. Однако есть ещё некоторые важные вещи, которые нужно обсудить.

Проблема в реализации withHover

О проблемах работы с компонентами высшего порядка сторонней разработки

Полагаем, вы уже оценили преимущества применения компонентов высшего порядка в деле повторного использования логики в различных компонентах без необходимости копирования одного и того же кода. Теперь зададимся вопросом о том, есть ли у компонентов высшего порядка недостатки. На этот вопрос можно ответить положительно, и мы с этими недостатками уже встречались.

Читайте также:  что значит футер 3 нитка диагональ

Итоги

Говоря о HOC в React, нужно помнить о двух важных вещах. Во-первых, HOC — это всего лишь паттерн. Компоненты высшего порядка даже нельзя назвать чем-то специфичным для React, несмотря на то, что они имеют отношение к архитектуре приложения. Во-вторых, для разработки React-приложений необязательно знать о компонентах высшего порядка. Вы вполне можете быть с ними незнакомы, но при этом писать отличные программы. Однако, как и в любом деле, чем больше у вас инструментов — тем качественнее может быть результат вашего труда. И, если вы пишете приложения с использованием React, вы окажете себе плохую услугу, не добавив HOC в свой «арсенал».

Уважаемые читатели! Пользуетесь ли вы компонентами высшего порядка в React?

Источник

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

Компоненты высшего порядка (HOC) представляют собой интересную технику в React, используемую для рефакторинга аналогичных компонентов, которые имеют почти одинаковую логику. Я знаю, что это звучит абстрактно и продвинуто. Тем не менее, это архитектурный шаблон, который не является специфичным для React, и, следовательно, вы можете использовать этот подход для разных вещей.

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

Есть несколько других учебных пособий, которые учат вас о HOC, но большинство из них предназначены для опытных разработчиков React. Когда я начал изучать React, у меня были проблемы с пониманием концепции компонентов более высокого порядка и того, как я мог бы включить HOC в свой проект для написания лучшего кода. Эта статья объяснит все, что вам нужно знать о HOC с нуля до люка.

Обзор

В третьей части этого руководства мы сосредоточимся больше на передовых практиках и вещах, которые следует учитывать при реализации компонентов более высокого порядка. Мы также кратко рассмотрим альтернативные шаблоны для совместного использования кода в React, такие как Render props.

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

Синтаксическая таблица ES6

Уже скоро приступим к коду. Но прежде чем мы это сделаем, вот несколько вещей, о которых я думаю, вы должны знать. Я предпочитаю использовать синтаксис ES6 везде, где это возможно, и он отлично работает с HOC. Для новичка HOC имел смысл, но некоторые из синтаксиса ES6 этого не сделали. Поэтому я рекомендую пройти этот раздел один раз, и вы можете вернуться сюда позже для справки.

Стрелочные функции

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

Функция без параметров

Функция с одним параметром

Функция с несколькими параметрами

Карринг в функциональном программировании

Хотя название предполагает, что оно имеет какое-то отношение к экзотическому блюду из популярной индийской кухни, это не так. Карринг помогает разбить функцию, которая принимает множество аргументов, на ряд функций, которые принимают один аргумент за раз. Вот пример:

Функция принимает только один аргумент и возвращает функцию, которая принимает другой аргумент, и это продолжается до тех пор, пока все аргументы не будут удовлетворены.

Тесно связанный термин называется частичным применением. Частичное приложение имеет дело с созданием новой функции путем предварительного заполнения некоторых аргументов существующей функции. Вновь созданная функция будет иметь арность (что соответствует количеству аргументов) меньше, чем у исходной функции.

Синтаксис распространения

Операторы распространения распространяют содержимое массива, строки или выражения объекта. Вот список вещей, которые вы можете сделать с помощью операторов распространения

Синтаксис распространения в вызовах функций

Синтаксис распространения в литералах массива

Синтаксис распространения в объектных литералах

Мне лично нравится, как три точки могут упростить передачу существующих props дочерним компонентам или создание новых props.

Оператор спреда в действии

Теперь, когда мы знаем основной синтаксис ES6 для построения HOC, давайте посмотрим, что они из себя представляют.

Функции высшего порядка

Что такое функция высшего порядка? Википедия:

Теперь, когда у нас есть хорошее представление о функциях высшего порядка, давайте посмотрим, на что способны компоненты высшего порядка.

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

Изображение ниже должно наглядно это продемонстрировать.

Функция withGreyBg принимает компонент в качестве входных данных и возвращает новый компонент. Вместо того, чтобы напрямую составлять компоненты карты и прикреплять тег стиля к каждому отдельному компоненту, мы создаем HOC, который служит этой цели. Компонент высшего порядка оборачивает исходный компонент и добавляет вокруг него тег

Заключение

Затем мы рассмотрели функции высшего порядка и то, как они работают. Наконец, мы коснулись компонентов высшего порядка и создали HOC с нуля.

Далее мы рассмотрим различные методы HOC с практическими примерами. Оставайтесь с нами. Поделитесь своими мыслями в разделе комментариев.

Источник

Higher-Order Components

A higher-order component (HOC) is an advanced technique in React for reusing component logic. HOCs are not part of the React API, per se. They are a pattern that emerges from React’s compositional nature.

Concretely, a higher-order component is a function that takes a component and returns a new component.

Whereas a component transforms props into UI, a higher-order component transforms a component into another component.

In this document, we’ll discuss why higher-order components are useful, and how to write your own.

Use HOCs For Cross-Cutting Concerns

We previously recommended mixins as a way to handle cross-cutting concerns. We’ve since realized that mixins create more trouble than they are worth. Read more about why we’ve moved away from mixins and how you can transition your existing components.

Components are the primary unit of code reuse in React. However, you’ll find that some patterns aren’t a straightforward fit for traditional components.

For example, say you have a CommentList component that subscribes to an external data source to render a list of comments:

Читайте также:  что делать если стало не о чем говорить с девушкой

Later, you write a component for subscribing to a single blog post, which follows a similar pattern:

You can imagine that in a large app, this same pattern of subscribing to DataSource and calling setState will occur over and over again. We want an abstraction that allows us to define this logic in a single place and share it across many components. This is where higher-order components excel.

The first parameter is the wrapped component. The second parameter retrieves the data we’re interested in, given a DataSource and the current props.

When CommentListWithSubscription and BlogPostWithSubscription are rendered, CommentList and BlogPost will be passed a data prop with the most current data retrieved from DataSource :

Note that a HOC doesn’t modify the input component, nor does it use inheritance to copy its behavior. Rather, a HOC composes the original component by wrapping it in a container component. A HOC is a pure function with zero side-effects.

Like components, the contract between withSubscription and the wrapped component is entirely props-based. This makes it easy to swap one HOC for a different one, as long as they provide the same props to the wrapped component. This may be useful if you change data-fetching libraries, for example.

Don’t Mutate the Original Component. Use Composition.

Resist the temptation to modify a component’s prototype (or otherwise mutate it) inside a HOC.

Mutating HOCs are a leaky abstraction—the consumer must know how they are implemented in order to avoid conflicts with other HOCs.

Instead of mutation, HOCs should use composition, by wrapping the input component in a container component:

This HOC has the same functionality as the mutating version while avoiding the potential for clashes. It works equally well with class and function components. And because it’s a pure function, it’s composable with other HOCs, or even with itself.

You may have noticed similarities between HOCs and a pattern called container components. Container components are part of a strategy of separating responsibility between high-level and low-level concerns. Containers manage things like subscriptions and state, and pass props to components that handle things like rendering UI. HOCs use containers as part of their implementation. You can think of HOCs as parameterized container component definitions.

Convention: Pass Unrelated Props Through to the Wrapped Component

HOCs add features to a component. They shouldn’t drastically alter its contract. It’s expected that the component returned from a HOC has a similar interface to the wrapped component.

HOCs should pass through props that are unrelated to its specific concern. Most HOCs contain a render method that looks something like this:

This convention helps ensure that HOCs are as flexible and reusable as possible.

Convention: Maximizing Composability

Not all HOCs look the same. Sometimes they accept only a single argument, the wrapped component:

Usually, HOCs accept additional arguments. In this example from Relay, a config object is used to specify a component’s data dependencies:

The most common signature for HOCs looks like this:

What?! If you break it apart, it’s easier to see what’s going on.

In other words, connect is a higher-order function that returns a higher-order component!

(This same property also allows connect and other enhancer-style HOCs to be used as decorators, an experimental JavaScript proposal.)

The compose utility function is provided by many third-party libraries including lodash (as lodash.flowRight ), Redux, and Ramda.

Convention: Wrap the Display Name for Easy Debugging

The container components created by HOCs show up in the React Developer Tools like any other component. To ease debugging, choose a display name that communicates that it’s the result of a HOC.

Higher-order components come with a few caveats that aren’t immediately obvious if you’re new to React.

Don’t Use HOCs Inside the render Method

React’s diffing algorithm (called Reconciliation) uses component identity to determine whether it should update the existing subtree or throw it away and mount a new one. If the component returned from render is identical ( === ) to the component from the previous render, React recursively updates the subtree by diffing it with the new one. If they’re not equal, the previous subtree is unmounted completely.

Normally, you shouldn’t need to think about this. But it matters for HOCs because it means you can’t apply a HOC to a component within the render method of a component:

The problem here isn’t just about performance — remounting a component causes the state of that component and all of its children to be lost.

Instead, apply HOCs outside the component definition so that the resulting component is created only once. Then, its identity will be consistent across renders. This is usually what you want, anyway.

In those rare cases where you need to apply a HOC dynamically, you can also do it inside a component’s lifecycle methods or its constructor.

Static Methods Must Be Copied Over

Sometimes it’s useful to define a static method on a React component. For example, Relay containers expose a static method getFragment to facilitate the composition of GraphQL fragments.

When you apply a HOC to a component, though, the original component is wrapped with a container component. That means the new component does not have any of the static methods of the original component.

To solve this, you could copy the methods onto the container before returning it:

However, this requires you to know exactly which methods need to be copied. You can use hoist-non-react-statics to automatically copy all non-React static methods:

Another possible solution is to export the static method separately from the component itself.

Refs Aren’t Passed Through

Источник

Строительный портал