Эта статья покажет вам, как вы можете создавать в React больше многоразовых и читаемых компонентов, придерживаясь всего нескольких простых правил.

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

Приложение доступно здесь:
https://github.com/kwdowik/reusable-components

Хорошо, приступим к приготовлению!

Чтобы приготовить вкусное блюдо, нужно придерживаться рецепта, который включает:

  • Многоразовая логика
  • Многоразовая презентация
  • Отдельные проблемы (логика и представление)
  • Расширяемость

Нашей отправной точкой будет CarsList компонент наmain ветке из репозитория reusable-components.

Ничего особенного. Компонент CarList просто извлекает автомобили из API и затем отображает их как элемент списка. У нас есть все в одном файле, логика и представление, и даже для этого файла, который очень прост, мы можем быстро ударить по стене и начать дублировать код, как только мы начнем добавлять новые компоненты.

Теперь, чтобы добавить все наши ингредиенты, нам нужно будет просмотреть /src/components/doc.md файл, где мы сможем найти, что нам нужно реализовать и как мы можем это сделать, так что давайте начнем!

Многоразовая логика

Наша задача будет заключаться в том, чтобы использовать нашу логику, отвечающую за доставку машин в разные места, и при этом следовать правилу DRY (Don't Repeat Yourself). Если вы следуете коду, перейдите в ветку ex1 / shared-logic.

Во-первых, нам нужно выделить нашу логику в отдельный пользовательский хук, назовем его useFetchCars:

... затем просто импортируйте этот хук внутри компонента CarList:

Благодаря этому мы делаем нашу логику загрузки автомобилей независимой от компонентов и можем повторно использовать ее в любом другом месте. Давайте добавим новый CarsTable компонент:

..и мы выполнили нашу первую задачу!

Многоразовая презентация

Зайдите в ветку ex2 / shared-presentation.

Пришло время для нашего второго ингредиента. Мы хотели бы повторно использовать наш компонент представления CarsList, который сейчас тесно связан с данными из useFetchCars хука, это нехорошо.

Предположим, что мы хотим отображать список автомобилей точно так же, но имея данные из другого источника (например, graphql), поэтому давайте передадим автомобили в качестве опоры компоненту CarsList:

..и мы уже достигли разделения ответственности, но теперь мы должны связать наш новый CarsList компонент с данными, чтобы ваши предыдущие функции остались неизменными. Добавьте CarsListContainer контейнер, который свяжет презентацию с логикой, и переименуйте компонент CarsList в CarsListPresentation:

CarsListPresentation компонент ничего не знает об источнике данных, который делает нашу презентацию пригодной для повторного использования. Отлично, мы выполнили очередное задание!

Расширяемость

Пожалуйста, зайдите в ветку ex3 / расширяемость.

Последней задачей будет сделать наш CarsListContainer расширяемым, но зачем нам это делать?

В текущей реализации, если бы нам пришлось добавить новую логику в контейнер, нам пришлось бы изменить наш контейнер, я бы не хотел этого делать, чтобы не нарушать принцип открытия / закрытия, который гласит: «Программные объекты должны быть открытыми для расширения, но закрытыми для модификации », поэтому, если в CarsListConatiner нужно будет добавить какое-либо новое поведение, я бы предпочел создать новый код, отвечающий только за это поведение в соответствии с принципом единой ответственности, а затем использовать состав. Мы можем добиться этого с помощью шаблона, который некоторое время используется в реакции Компоненты высшего порядка.

Наш HOC получит CarsPresentation компонент в качестве аргумента и передаст автомобили в качестве опоры.

в конце мы вызываем withFetchCarsHOC с CarsListPresentation компонентом, и все готово!

Если мы хотим создать новый HOC с другим поведением, мы можем использовать метод compose, чтобы связать его с другими

Приятного аппетита

Проверим, добавили ли мы все необходимые ингредиенты:

  • Многоразовая логика. Мы сделали нашу логику многоразовой, благодаря извлечению ее с помощью useFetchCars хука.
  • Многоразовая презентация CarsListPresentation. Получите данные как опору, которая делает наш компонент логически независимым и многоразовым.
  • Раздельные задачи (логика и представление), наша логика и представление разделены, потому что у нас есть CarsListPresentation, который ничего не знает об источнике данных, и useFetchCars ловушка, которая не знает о презентации.
  • Расширяемость. После создания withFetchCarsHOC мы можем добавить новое поведение в CarsList составным способом, не изменяя существующую реализацию в соответствии с принципом открытия / закрытия.

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

Спасибо за внимание!

Twitter: k_wdowik