Перевод "Presentational and Container Components" от Dan Abramov
Есть простой шаблон, который я нахожу очень полезным при написании приложений на React. Если вы какое-то время работаете с React, то, вероятно, вы о нем уже знаете. Данная статья хорошо объясняет это, но я бы хотел кое-что добавить.
Вам будете гораздо проще повторно использовать компоненты, если вы разделите их на две категории. Я называю их Контейнер и Презентационный компоненты*. Но также слышал Толстый и Худой, Умный и Глупый, Имеющий состояние и Чистый, соответсвенно. Они не совсем идентичны, но в основе лежит одна идея.
Мои презентационныe компоненты:
Мой компоненты-контейнеры:
Я кладу их в разные папки, чтобы сделать это различие наглядным.
Помните, компоненты не должны извергать DOM. Они необходимы только для обеспечения структуры границ в проблеме интерфейса.
Воспользуемся этим.
Предлагаю начать построение вашего приложения с простых презентационных компонентов. В процессе вы поймете, что вы передаете большое количество параметров props через промежуточные компоненты. Когда заметите, что некоторые не используют props, а лишь перенаправляют их вниз и необходимо перемонтировать все эти промежуточные компоненты в любое время, когда дочерним компонентам необходима новая порция данных, то это подходящее время ввести некоторый компонент-контейнер. Это позволит получить данные и поведение props к компонентам страницы не затрагивая компоненты в середине дерева.
Рефакторинг осуществляется постоянно, поэтому не старайтесь написать все отлично с первого раза. Экспериментируя с этим паттерном, вы сможете развить интуитивное понимание, когда необходимо ввести контейнер, также , как вы знаете когда нужно извлечь функцию. Мой курс на Redux Egghead может помочь вам в этом!
Важно понимать, что разделение между компонентами не техническое, а скорее связано с их целями.
И наоборот, есть несколько связанных (но разных!) технических различий:
setState()
, а некоторые нет. Если контейнеры склонны к наличию состояния, а презентационные компоненты нет, то это не является жестким правилом. Контейнер не может иметь состояния, а презентационный компонент наоборот.props
и state
. Чистые компоненты могут быть определены и как классы, и как функции, и могут иметь свое собственное состояние или нет. Другой важный аспект чистых компонентов в том, что они не опираются на глубокие мутации в state
и props
, поэтому их производительность может быть оптимизирована за счет использования shouldComponentUpdate()
. Сейчас только классы могут определять shouldComponentUpdate()
, но это может измениться в будущем.Оба представления компонентов могут принадлежать одной из этих групп. В моей практике, презентационные компоненты, как правило, являются чистыми функциями, а контейнеры классами чистого состояния. Это не правило, а скорее наблюдение. Я встречал и противоположные случаи, которые были обоснованы при определенных обстоятельствах.
Не принимайте подобное разделение на презентационные компоненты и контейнеры как догму. Иногда это не важно или тяжело провести линию между ними. Если вы не уверены каким должен быть компонент, то возможно еще слишко равно причислять его к определенной группе и правильное решение придет позже. Не парьтесь!
Gist от Michael Chan.
*В ранней версии статьи я называл их “умный” и “глупый” компоненты, но это было очень грубо и, самое главное, не объяснил разницу в их целях. Я нахожу новые термины более лучшими и, надеюсь, вы тоже!
**В ранней версии статьи я утверждал, что презентационные компоненты должны содержать только другие презентационные компоненты. Сейчас я не думаю так. Является компонент презентационным или контейнером зависит от реализации. Вы должны быть в состоянии заменить презентационный компонент с контейнером без изменения места вызова на сайте. Таким образом, презентационные компоненты и контейнеры могут отлично содержать в себе другие презентационные компоненты или контейнеры.
-Dan Abramov