Создание гибких, легко тестируемых и повторно используемых представлений в React, не заканчиваясь «адом разметки»

Более доступная, удобочитаемая, адаптированная для мобильных устройств и актуальная версия этой истории доступна в моем личном блоге!

Это первая статья из серии из трех статей о субкомпонентах React. Часть 2 и Часть 3 доступны здесь и здесь.

Каждый проект React, над которым я работал, будь то личный или связанный с работой, в какой-то момент становился настолько большим, что их кодовую базу становилось трудно понять. Каждое небольшое изменение требовало большего обдумывания, но приводило к множеству несоответствий и взломов. Среди многих проблем, которые у меня были с такими кодовыми базами, отсутствие возможности повторного использования некоторых представлений было основной: это приводило к большому количеству копирования / вставки кода сложных компонентов / представлений, чтобы гарантировать, что они выглядят одинаково, и полученный дублированный код не работал Это не упрощает поддержку или тестирование.
Использование шаблона подкомпонента может помочь решить все эти проблемы.

Что такое подкомпонент?

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

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

В этом контексте подкомпоненты определяются как компоненты, которые имеют собственное определение, объявленное в другом родительском компоненте, и могут использоваться только в контексте этого родительского компонента. В приведенном выше примере компонент "Заголовок", например, существует только в рамках компонента "Статья". Он не может быть обработан сам по себе.
Я лично не уверен в названии, но это лучший термин, который я нашел для обозначения этого шаблона, который я научился ценить в своих проектах.
Подкомпоненты можно увидеть в нескольких библиотеках, таких как Recharts или Semantic-UI. Последний относится к субкомпонентам как модули, коллекции и представления в своей библиотеке и дает вам возможность отображать представления так же, как указано выше.
Этот тип шаблона действительно полезен:

- для обеспечения единообразия просмотров: вы можете фактически отображать любые данные, используя компонент статьи выше. Здесь важно то, что независимо от его назначения, он будет выглядеть одинаково во всем приложении.
- Чтобы ваш код был точным и чистым: заголовок, комментарии, подзаголовок, метаданные имеют смысл внутри статьи и могут использоваться только в ней (т.е. там, где они имеют смысл, поскольку эти компоненты используются только в контексте статьи).
- иметь легко проверяемые представления : для тестирования таких компонентов Jest и тестирование снимков - наши союзники. Это дает нам возможность быстро протестировать любую комбинацию подкомпонентов при использовании Article. Позже мы увидим, как использовать Jest для проверки такого паттерна.

Как создавать подкомпоненты

В этом разделе мы собираемся шаг за шагом создать компонент Article, сначала пытаясь реализовать подкомпонент Title.
Первое, что нам нужно для создания подкомпонентов внутри компонента, это утилита для поиска дочерних элементов по «типу» или «имени», чтобы React знал, как отображать наш субкомпонент Title. Мы передадим в эту утилиту два параметра:

  • children: список дочерних элементов Article
  • компонент: компонент, который мы хотим найти в списке дочерних элементов, в нашем примере это будет Title.

Вот как выглядит утилита findByType:

Теперь, когда у нас есть findByType util, мы можем приступить к написанию нашего Article компонента и Title подкомпонента:

Теперь у нас есть возможность использовать компонент Article и его подкомпонент Title как таковые:

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

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

Использование тестирования Jest и моментальных снимков для тестирования подкомпонентов

Моментальное тестирование наших подкомпонентов, вероятно, является самым быстрым и безопасным способом убедиться, что любая комбинация подкомпонентов в компоненте Article будет правильно отображаться. Для этого мы будем использовать как Jest, так и Enzyme. Вот как вы можете написать тесты для нашего примера:

Последнее замечание

При написании этой статьи я заметил, что субкомпоненты не отображались в IE 11 и Edge, когда они были связаны с Babel 6.26.0 и Webpack 3.10. Возможно, это влияет на другие версии, я еще не проверял, но все, что я знаю, это то, что это повлияло только на связанное приложение, оно отлично работало, когда проект работал с Webpack Dev Server.

Что случилось? Причина здесь была обнаружена при отладке findByType util. child.type.displayName || child.type.name возвращал undefined в IE и Edge по следующей причине: «type здесь ссылка на конструктор компонента. Таким образом, если вы сделаете child.type.name, он будет ссылаться на свойство name в конструкторе - не поддерживается в IE. »

Ссылка: https://github.com/facebook/react/issues/9803

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

Если вам понравилась эта статья, не забудьте нажать кнопку Хлопнуть, и если у вас есть другие вопросы, я всегда доступен в Твиттере или на моем сайте. Вы также можете подписаться на мою Среднюю публикацию, чтобы не пропустить мой следующий пост.

Удачного дня
Максим