DevGang
Авторизоваться

Контроль сложности компонентов React с помощью инверсии управления

Наверняка в какой-то момент вы обнаруживали, что сидите за столом, загроможденным случайными вещами... Как же до этого дошло? Медленно, но верно вы размещали все больше и больше вещей на идеально аккуратном столе, пока это не превратилось в мучение.

Это похоже на то, что происходит в компонентах React. Мы начинаем просто и чисто, но по мере добавления новых функций код становится грязным и сложным для поддержки.

Давайте посмотрим, как мы можем предотвратить это.

Начнем с (упрощенного) запроса на подтверждение, как этот:

const ConfirmationPrompt = () => (
  <div>
     <p>Are you sure?</p>
     <div>
       <button>Cancel</button>
       <button>Confirm</button>
     </div>
  </div>
)

// Used as <ConfirmationPrompt />

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

const ConfirmationPrompt = ({destructive}) => (
  <div>
     {destructive && (<p>☠️ DANGER ☠️</p>)}
     <p>Are you sure?</p>
     <div>
       <button>Cancel</button>
       <button>Confirm</button>
     </div>
  </div>
)

// Used as
<ConfirmationPrompt destructive />

Все вроде бы хорошо, но что, если некоторые действия опасны и должны инициировать уведомление по электронной почте? Мы могли бы просто скопировать ту же логику, но заметили, что быстро столкнулись с одной большой проблемой:

Возможные вариации нашего компонента растут в геометрической прогрессии.

const ConfirmationPrompt = ({destructive, triggersNotifications}) => (
  <div>
     {triggersNotifications && (<p>ℹ️ Email will be sent</p>)}
     {destructive && (<p>☠️ DANGER ☠️</p>)}
     <p>Are you sure?</p>
     <div>
       <button>Cancel</button>
       <button>Confirm</button>
     </div>
  </div>
)

// Used as 
<ConfirmationPrompt
 destructive
 triggersNotifications
/>

В нашем первом примере было 1 возможное состояние, во втором - 2 (разрушающее и неразрушающее), а в третьем - уже 4!

Помните: шаблоны сохраняются, а код, который изменился, склонен продолжать меняться, поэтому лучше решить эту проблему как можно раньше.

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

Этот простой и мощный инструмент называется инверсией контроля.

По сути, мы возвращаем контроль пользователю нашего компонента, делая его более гибким и адаптируемым.

Выглядит это следующим образом:

const ConfirmationPrompt = ({header}) => (
  <div>
     {header} //Our caller decides what to put here
     <p>Are you sure?</p>
     <div>
       <button>Cancel</button>
       <button>Confirm</button>
     </div>
  </div>
)

// Used as 
<ConfirmationPrompt
 header={
    <>
       <WillNotifyMessage/>
       <DangerZoneMessage/>
    </>
 }
/>

// or

<ConfirmationPrompt
 header={<WillNotifyMessage/>}
/>

// and any other use case that comes up!

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

К сожалению, это не поможет нам сохранить чистоту рабочего стола, но инверсия контроля имеет множество применений в React, и вы найдете примеры с различными вариациями. Идея, лежащая в ее основе, всегда одна и та же - вернуть управление вызывающей функции.

Источник:

#JavaScript #React #Начинающим
Комментарии
Чтобы оставить комментарий, необходимо авторизоваться

Присоединяйся в тусовку

В этом месте могла бы быть ваша реклама

Разместить рекламу