Что вы делаете, когда у вас есть «одинаковые, но разные» компоненты, и вы хотите их повторно использовать?
Давайте посмотрим на пример
Кнопка загрузки
У нас есть 2 очень похожих компонента:
Они оба о загрузке файлов. Однако одна кнопка используется для создания словаря, а другая - данных. Различия между Data и Dictionary на данный момент не актуальны.
Обе кнопки имеют аналогичное поведение. Они открывают файловую систему для выбора файлов. При их выборе файлы загружаются в нашу систему.
Однако есть несколько отличий.
- Они должны создать другую сущность, а это значит, что они попадают в другую конечную точку нашего API.
- Текст кнопки другой.
- Они принимают разные типы пантомимы.
Сначала мы создали компонент UploadButton
для данных. Когда мы хотели реализовать UploadButton
для словарей, мы столкнулись с тремя возможными шаблонами для повторного использования компонента:
Вариант 1. Используйте опору для установки типа
// In our Data page <UploadButton type="data" /> // In our Dictionary page <UploadButton type="dictionary" />
Таким образом, UploadButton очень легко использовать повторно. Однако реализация UploadButton не очень элегантна. Мы должны проверить опору type
, чтобы использовать ту или иную вещь.
Наш UploadButton
будет расти вместе с условными операторами, если мы добавим к нему функциональность. Также будет очень обременительно, если мы когда-нибудь захотим ввести новую сущность помимо данных и словаря.
Вариант 2. Передайте различия как реквизиты
// in our Data page Component <UploadButton text="Upload data" acceptedValues={ this.props.dataAcceptedValues } handleUpload={ this.props.startDataUpload } /> // in our Dictionary page Component <UploadButton text="Upload dictionary" acceptedValues={ this.props.dictionaryAcceptedValues } handleUpload={ this.props.startDictionaryUpload } />
Само по себе это выглядит хорошо. Однако, когда вы используете его в компоненте, который также имеет некоторые другие кнопки и компоненты, props
этого компонента становится огромным списком. Делает компонент трудным для чтения и понимания.
Вариант 3. Создание новых компонентов
// in our Data page Component <UploadDataButton /> // in our Dictionary page Component <UploadDictionaryButton />
Это будет означать, что нам нужны два новых компонента: UploadDataButton
и UploadDictionaryButton
.
// in UploadDataButton <UploadButton text="Upload data" acceptedValues={ this.props.dataAcceptedValues } handleUpload={ this.props.startDataUpload } /> // in UploadDictionaryButton <UploadButton text="Upload dictionary" acceptedValues={ this.props.dictionaryAcceptedValues } handleUpload={ this.props.startDictionaryUpload } />
Создав их как отдельные компоненты, мы упростили их использование и повторное использование. Просто импортируйте это. Не нужно передавать prop
. Мы можем сформулировать эту закономерность по следующему принципу:
Больше компонентов с меньшим количеством логики против меньшего количества компонентов с большей логикой
Если нам когда-нибудь понадобится добавить какую-то новую функцию, мы можем легко сделать это в автономном компоненте. Если функция, которую нам нужно добавить, является общей для обоих, у нас также будет UploadButton
для нее.
Вывод
Этот шаблон принес нам несколько дополнительных функций:
- Легко повторно использовать компоненты
- Компоненты с меньшим количеством
props
- Гибкость для будущих функций
Обратной стороной является увеличение количества используемых компонентов с 1 до 3. В нашем случае это компромисс, на который мы готовы пойти.
Это простой сценарий, иллюстрирующий закономерность. Мы успешно применили его к более сложным ситуациям.
Нам нравится получать отзывы от сообщества, поэтому не стесняйтесь оставлять комментарии.
Спасибо за чтение!
Изначально опубликовано в Блоге Onedot.