React 16 принес нам React Portals, однако они по-прежнему требуют от нас самостоятельной работы с элементами DOM. Сегодня мы представляем реакцию-канал, еще один способ рендеринга компонентов вне иерархии компонентов.
TL; DR
react-pipeit - это библиотека, которая экспортирует два основных компонента:
<Inlet />
и<Outlet />
. Дети, переданные на вход, будут отображаться во всех подключенных выходах.
Различные каналы управляются
registry
, совместно используемым через контекст a<ConduitProvider />
. Вы также можете соединить два или более приложения React с помощью react-pipeline, создав единый реестр и поделившись им между всеми<ConduitProvider />
.
Проблема
Несколько месяцев назад мне пришлось реализовать некоторые компоненты для отображения диалоговых окон подтверждения и модальных окон. Из-за того, как работают контексты стекирования CSS, я оказался в кроличьей норе.
Когда вам нужно отрендерить диалог вниз по дереву DOM, довольно часто оказывается, что вы находитесь внутри контекста стекирования, отличного от остальной части вашего пользовательского интерфейса. В этих случаях вам нужно, чтобы дочерний элемент был помещен вне его естественного контейнера, чтобы он отображался в другом месте.
Эта проблема была решена с помощью react-portal, который был частью стандартного React API с React 16. Однако API порталов требует, чтобы мы сами занимались управлением узлами DOM.
render() {
return ReactDOM.createPortal(
this.props.children,
domNode,
);
}
Поскольку наш пользовательский интерфейс довольно сложен и имеет несколько модальных окон, диалоговые окна и всплывающие подсказки могут располагаться на разных уровнях, использование порталов не представлялось жизнеспособным. Я хотел иметь возможность определять слои нашего приложения в стиле React.
Представляем React-pipeline
React-pipeline - это библиотека, которая экспортирует два основных компонента: <Inlet />
и <Outlet />
.
С порталами React вам нужно выбрать, в каком узле DOM вы хотите отобразить дочерние элементы. С помощью react-pipeline вы визуализируете дочерние элементы внутри Inlet, и эти дочерние элементы будут отображаться в подключенных Outlets, так что вы сможете избежать работы с DOM.
Чтобы подключить один или несколько входов к одному или нескольким выходам, вы должны пометить их с помощью стойки label
. Кроме того, вы можете использовать стойки onConnect
и onDisconnect
, если вам нужно получать уведомления, когда вход или выход подключаются или отключаются.
Состояние подключенных трубопроводов и процесс подключения / отключения управляется registry
. Реестр используется <ConduitProvider />
компонентом через контекст, поэтому и входы, и выходы могут подключаться при подключении или отключении.
Если вам нужно, вы даже можете подключить два или более приложения React, если вы используете один и тот же registry
для каждого провайдера.
Практические варианты использования
Уровни приложений
Один из вариантов использования, где достаточно хорошо работает react-pipeline, - это создание разных уровней для приложения.
Если вам нужны разные слои для всплывающих подсказок, раскрывающихся списков, всплывающих окон или модальных окон, вы можете сделать что-то вроде этого:
Вы можете создать столько слоев, сколько захотите, и разместить их в разных частях приложения, решив ранее упомянутую проблему стекирования CSS.
Отдельные компоненты
Еще одна замечательная вещь, которую вы можете сделать с помощью react-pipeit, - это отсоединить ваши компоненты, разбив их на разные части, чтобы отрисовать их отдельно.
Представьте, например, что у вас есть компонент для редактирования статей. В этом компоненте вы визуализируете заголовок, контент и панель инструментов, но при желании хотите разрешить пользователям вашего компонента отображать панель инструментов где-нибудь еще. В этом случае вы можете сделать что-то вроде этого:
Это здорово, потому что компонент Editor даже не привязан к реакции-каналу, он просто принимает контейнер. Это может быть даже компонент с отслеживанием состояния, и мы сможем отображать вещи в разных частях нашего приложения.
Рендеринг между приложениями
Возможно, вы разрабатываете приложение, отличное от React, которое использует React только для некоторых его частей. Если это так, и вам нужны разные реагирующие части, чтобы как-то общаться, вы можете сделать что-то вроде этого:
С большой властью приходит большая ответственность
Каналы - это мощное средство, но имейте в виду, что вы будете визуализировать элементы за пределами их естественного объема. Это может быть проблема с CSS. Если вы не будете осторожны, стили не будут каскадироваться так, как вы ожидаете.
Мы обнаружили, что реакция-проводник - один из полезных инструментов в нашем арсенале, но не всегда лучший инструмент для работы. Каналы увеличивают сложность вашего приложения. Если вы будете злоупотреблять им, вашему коду станет труднее следовать.