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

Используйте библиотеку как плагин

При работе со сторонней библиотекой нужно учитывать следующее.

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

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

Шаблон “Адаптер” в React

Один из способов убедиться, что все упомянутые выше пункты учтены,  —  использовать шаблон “Адаптер”.

Шаблон “Адаптер” преобразует интерфейс класса в другой интерфейс, ожидаемый клиентами. Адаптер позволяет классам работать вместе, что в противном случае было бы невозможно из-за несовместимых интерфейсов.

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

В React допустимы два типа оболочек:

  • оболочка компонента (для обертывания компонентов библиотеки);
  • оболочка функций (для обертывания библиотечных функций).

В этой статье мы сосредоточимся на оболочках компонентов. Рассмотрим пример.

Оболочка компонента в действии

Для примера мы создадим адаптер для React Flow  —  библиотеки для построения диаграмм.

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

  • визуализация основных узлов диаграмм;
  • реакция при выборе узла;
  • реакция при отсутствии выбора.

Чтобы добиться этого, сначала внедрим Diagram Adapter:

import ReactFlow, { isNode } from "react-flow-renderer";

const DiagramAdapter = ({ nodes, onActivateNode, onDeactivateAll }) => {
const onSelectionChange = (elements) => {
if (elements) {
const selectedNodes = elements.filter((els) => isNode(els));

if (selectedNodes.length > 0) {
onActivateNode(selectedNodes[0].id);
}
}
};

const onPaneClick = () => onDeactivateAll();

return (
<div style={{ height: 650 }}>
<ReactFlow
elements={nodes}
onSelectionChange={onSelectionChange}
onPaneClick={onPaneClick} />
</div>
);
}

export default DiagramAdapter;

В приведенном выше коде мы обернули компонент ReactFlow и привязали к нему несколько слушателей событий. Затем эти слушатели преобразуют данные из событий и вызывают функции onActivateNode и onDeactivateAll, передаваемые родительским компонентом адаптера.

Таким образом, родительскому компоненту даже не нужно знать, какая библиотека импортирована. Он просто знает, что onActivateNode и onDeactivateAll доступны для использования.

К слову, адаптер также можно использовать вот так:

function App() {
const nodes = [
{
id: "node_0",
position: { x: 150, y: 25 },
data: { label: "Start" }
},
{
id: "node_1",
position: { x: 150, y: 225 },
data: { label: "End" }
},
{
id: "node_0-node_1", type: "step", source: "node_0", target: "node_1"
}
];

const onActivateNode = (node) => {
console.log("Activated", node);
};

const onDeactivateAll = (node) => {
console.log("Deactivated all");
};

return (
<DiagramAdapter
nodes={nodes}
onActivateNode={onActivateNode}
onDeactivateAll={onDeactivateAll} />
);
}

Заключение

Вы успешно применили шаблон проектирования “Адаптер” в приложении на React!

Теперь можно пользоваться преимуществами отделения приложения от сторонних библиотек: приложение не знает про библиотеки, модели данных согласованы, а степень связанности минимальна.

Читайте также:

Читайте нас в Telegram, VK и Дзен


Перевод статьи Kenneth Angelo Reyes: How to Use the Adapter Design Pattern in React

Предыдущая статьяMongoDB: ограничение отображаемых документов 
Следующая статья5 весомых причин познакомиться с паттерном “Компоновщик”