Три шаблона проектирования компонентов React

Три шаблона проектирования компонентов React

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

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

1. Presentational and Container Component Pattern

Этот паттерн, придуман Дэном Абрамовым. В нем компоненты делятся на:

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

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

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

Мы создали компонент TvShowsContainer, который извлекает данные из API, когда компонент монтируется в приведенном выше примере. Он также передает эти данные презентационному компоненту ItemsList, который мы создали ранее. Преимуществом этого шаблона является разделение задач и возможность повторного использования компонентов. Другие компоненты могут повторно использовать презентационный компонент ItemList для отображения данных, поскольку он не тесно связан с TvShowsListContainer. Посмотреть рабочее приложение можно здесь.

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

2. Provider Pattern

Одной из основных проблем, с которой сталкиваются разработчики React, является проп дриллинг (рrop drilling). Проп дриллинг — это сценарий, в котором данные (props) передаются различным компонентам, пока не доберутся до компонента, они необходимы. Хотя проп-дриллинг — это не плохо, он становится проблемой, когда несвязанные компоненты обмениваются данными, что приводит нас к идеи Provider Pattern. Этот паттерн позволяет нам хранить данные в центральном месте, например, React Context и Redux store. Provider/Store может передать эти данные любому компоненту, которому они нужны, напрямую, без проп-дриллинга.

Представьте себе внедрение темного режима для веб-приложения и создание несвязанных компонентов, реагирующих на изменение темы, вызванное другим компонентом. Мы можем добиться этого, используя шаблон Provider. Создадим объект контекста React для хранения значения темы.

В файле App.js мы оборачиваем импортированные компоненты с помощью ThemeContext.Provider. Это дает различным компонентам и их дочерним элементам доступ к созданному объекту контекста.

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

Чтобы получить доступ к ThemeContext в компонентах, мы можем использовать useContext хук, представленный в React 16.9.

Хотя контекст упрощает передачу данных между компонентами, рекомендуется использовать этот подход с осторожностью, поскольку он затрудняет повторное использование компонентов. Вы можете получить доступ к рабочему приложению приведенного выше примера здесь. Паттерн Provider используется в React Router и React-Redux.

3. Compound Components Pattern

Составные компоненты (Compound Components)— это компоненты, которые имеют общее состояние и работают вместе для достижения общей цели. Примером могут служить HTML-элементы select и option. В сочетании вместе они создают выпадающее меню, но сами по себе они мало что делают.

Паттерн Compound Components используется в популярных библиотеках пользовательского интерфейса React, например: Ant Design и Material UI. Ниже представлена реализация компонента Menu в Material UI.

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

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

По мере поступления новых требований компонент становится слишком сложным и непригодным для использования. Паттерн Сompound Сomponent обеспечивает более чистый способ достижения необходимого результата. Существует два способа создания компонента React с использованием паттерна Сompound Сomponent: React.cloneElement и React Context. Я буду использовать подход React Context для примера ниже.

Мы создали объект контекста MenuContext для компонента Menu с помощью функции createContext, предоставляемой React Context API. Это сохранит общее состояние для компонентов Menu и MenuItem. Мы также создали состояние для выбранного пункта меню. Это позволит нам обновить контекст аналогично тому, что мы сделали в Provider Pattern, поскольку Context API по своей природе не имеет состояния.

Следующим шагом является создание компонента MenuItem.

Первое, что здесь делается, — это создание пользовательского хука useMenuContext для проверки того, используется ли MenuItem вне компонента Menu, и выдачи ошибки, если это произойдет. После этого мы создаем MenuItem, используя общее состояние с компонентом Menu, чтобы определить, какой стиль применить к выбранному MenuItem, и изменить выбранный элемент при клике на элемент меню.

Подводя итог, мы соединяем эти компоненты вместе в компоненте приложения.

Вы можете просмотреть полный код приложения здесь.

Заключение

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

Автор: Samaila Bala

Источник: blog.openreplay.com

Редакция: Команда webformyself.

Читайте нас в Telegram, VK, Яндекс.Дзен

Метки:

Похожие статьи:

Комментарии Вконтакте:

Комментарии запрещены.