Эта статья покажет вам, как вы можете создавать в 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