Новий підхід до реагування на компонентний дизайн

У 2015 році Ден Абрамов написав статтю "Презентаційні та контейнерні компоненти", яку деякі новоприбулі реагують неправильно як заповіді. Насправді, я сам натрапив на статтю та багато інших, що повторюють її вчення, і я подумав, що це повинен бути найкращий спосіб розділити проблеми між компонентами .

Але сам Дан Абрамов пізніше звернувся до спільноти, щоб той чіплявся до дизайнерських зразків, які він окреслив.

Працюючи з React вже більше року, я натрапив на власні шаблони дизайну і тут спробую їх формалізувати. Сприймайте ці ідеї з достатньою кількістю солі, це лише мої власні спостереження, які я знайшов конструктивними.

Рятуючись від дихотомії

Протягом тривалого часу компоненти широко класифікуються як розумні чи німі, контейнерні або презентаційні, із статусом чи без громадянства, чисті чи нечисті. Існує багато термінології, але всі вони означають приблизно одне і те ж. Розумні компоненти знають, як пов’язати ваш додаток, а німі компоненти просто беруть дані, щоб представити їх кінцевому користувачеві. Це корисна відмінність, але насправді справа не в тому, як я роздумую над розробкою компонентів.

Проблема мислення Container vs.

До дизайну компонентів краще підходити, відкладаючи деталі реалізації та продумуючи інтерфейси компонентів . Особливо важливо подумати про те, які налаштування повинен дозволяти компонент і які неявні та явні залежності повинен включати компонент.

Представляємо трихотомію

Трихотомія? Це навіть слово? Не знаю, але ти розумієш ідею. Я прийшов до думки, що компоненти React потрапляють в один із трьох контейнерів.

Універсальні компоненти

Це компоненти, які можна використовувати багато разів у будь-якому застосуванні .

Ці компоненти:

  • Має бути багаторазовим
  • Має бути дуже настроюваним
  • Якщо не знати додатки конкретного коду , включаючи моделі, магазини, послуги і т.д.
  • Повинні звести до мінімуму залежності від сторонніх бібліотек
  • Потрібно рідко використовувати безпосередньо у вашому додатку
  • Потрібно використовувати як будівельні блоки для глобальних компонентів
  • Може закінчуватися суфіксом “Base” (наприклад, ButtonBase, ImageBase)

Це основні компоненти, які є агностичними щодо застосувань, і їх не обов’язково використовувати безпосередньо у компонентах View, оскільки вони часто занадто налаштовуються. Використовувати їх безпосередньо у компонентах View, означало б багато копіювати та вставляти одну і ту ж плиту котла. Ви також ризикуєте розробниками зловживати надзвичайно настроюваним характером компонентів таким чином, що створює непослідовний досвід роботи у вашій програмі.

Глобальні компоненти

Це компоненти, які можна використовувати багато разів в одному застосуванні .

Ці компоненти:

  • Має бути багаторазовим
  • Має бути мінімально настроюваним
  • Може використовувати спеціальний код програми
  • Слід впровадити універсальні компоненти , обмежуючи їхню настроюваність
  • Потрібно використовувати як будівельні блоки для компонентів View
  • Часто пов'язують один на один із екземплярами моделей (наприклад, DogListItem, CatCard)

Ці компоненти можна багаторазово використовувати у вашій програмі, але їх не легко перенести в інші програми, оскільки вони залежать від логіки програми. Це будівельні блоки для компонентів View та інших глобальних компонентів.

Вони повинні бути мінімально настроюваними, щоб забезпечити узгодженість вашої програми. Додатки не повинні мати тридцять різних варіантів кнопок, а навпаки, повинні мати кілька різних варіантів кнопок. Це повинно бути застосовано, беручи високо настроюваний компонент Universal ButtonBase та вписуючи в нього стилі та функціональність у вигляді компонента Global Button. Глобальні компоненти часто приймають іншу форму як подання даних моделі домену.

Перегляд компонентів

Це компоненти, які використовуються лише один раз у вашому додатку .

Ці компоненти:

  • Якщо НЕ турбуватися про можливості повторного використання
  • Ймовірно, будуть управляти державою
  • Отримайте мінімальний реквізит
  • Пов’язати між собою глобальні компоненти (і, можливо, універсальні компоненти)
  • Часто вирішують маршрути додатків
  • Часто підтримують спеціальний сюжет огляду нерухомості
  • Часто мають велику кількість залежностей
  • Повинні бути будівельними блоками для вашої програми

Це компоненти вашого найвищого рівня, які склеюють компоненти багаторазового використання та навіть інші представлення. Це часто будуть компоненти, які вирішують маршрути, і можуть відображатися у вигляді компонентів на рівні сторінки. Вони важкі в стані і легкі в реквізиті. Це те, що Ден Абрамов вважав би контейнерними компонентами.

Кнопка PromiseButton

Давайте подивимося на універсальну та глобальну реалізацію кнопки обіцянки та подивимося, як вони порівнюються. Кнопка обіцянки діє як звичайна кнопка, якщо обробник onClick не поверне обіцянку. У разі повернення обіцянки кнопка може умовно відтворювати вміст на основі стану обіцянки.

Зверніть увагу, як PromiseButtonBase дозволяє нам контролювати, що відображати в будь-який момент життєвого циклу обіцянки, але PromiseButton випікається в чиряку PulseLoader під час очікування. Кожного разу, коли ми використовуємо PromiseButton, ми гарантуємо анімацію завантаження чирок, і нам не доведеться турбуватися про дублювання цього коду або надання непослідовного досвіду завантаження, включивши в нашу програму кілька завантажувальних анімацій з декількох кольорів. PromiseButtonBase можна налаштувати, але PromiseButton є обмежувальним.

Структура каталогу

Далі показано, як ми можемо організувати компоненти за цією схемою.

App/ App.js Views/ DogListView/ Global/ Models/ Dog/ DogListItem/ Image/ PromiseButton/ Universal/ ImageBase/ PromiseButtonBase/

Залежності компонентів

Нижче показано, як зазначені вище компоненти залежать один від одного.

/* App.js */ import { DogListView } from './Views' /* DogListView.js */ import { DogListItem } from 'App/Global/Models/Dog' /* DogListItem.js */ import Image from '../../Image', import PromiseButton from '../../PromiseButton' /* Image.js */ import { ImageBase } from 'Universal' /* PromiseButton.js */ import { PromiseButtonBase } from 'Universal'

Наш компонент View залежить від глобального компонента, а наші глобальні компоненти залежать від інших глобальних компонентів, а також універсальних компонентів. Цей потік залежностей буде досить поширеним. Зверніть увагу також на використання абсолютного та відносного імпорту. Приємно використовувати відносний імпорт під час втягування залежностей, що знаходяться в одному модулі. Крім того, приємно використовувати абсолютний імпорт під час введення залежностей між модулями або коли структура каталогу глибоко вкладена або часто змінюється.

Проблема моделі Container vs Presentational полягає в тому, що вона надто старається визначити відповідальність компонента з точки зору внутрішньої роботи компонента. Ключовим виводом є перегляд дизайну компонентів з точки зору інтерфейсів компонентів . Менше має значення реалізація, яка дозволяє компоненту задовольнити свій контракт. Важливо продумати, які налаштування повинен дозволяти компонент і які неявні та явні залежності повинен включати компонент.

Якщо ви вважаєте ці думки корисними і хотіли б побачити більше моїх ідей, сміливо перегляньте це репо, яке я використовую, щоб підтримати свої думки та найкращі практики для написання програм React / Redux.