Создание гибких, легко тестируемых и повторно используемых представлений в 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 для каждого из моих подкомпонентов, чтобы гарантировать, что у них есть имя. Вот как это должно выглядеть на нашем примере:
Если вам понравилась эта статья, не забудьте нажать кнопку Хлопнуть, и если у вас есть другие вопросы, я всегда доступен в Твиттере или на моем сайте. Вы также можете подписаться на мою Среднюю публикацию, чтобы не пропустить мой следующий пост.
Удачного дня
Максим