Примечание I. Если вы не знаете, что такое утиный ввод, я рекомендую вам прочитать мою предыдущую статью JavaScript и утиный ввод. Там я пытаюсь максимально просто объяснить, что это такое в контексте JavaScript.

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

Как?

Если мы подумаем об утиной печати по определению, это значит пройти «крякву», когда тот, кто получает, ожидает «утку», но это все еще работает, потому что «получатель», ожидающий «утку», не заботится о расе ( тип / экземпляр), но некоторые из его поведения (методы).

Но как применить это в контексте React? Это сложно, но мы собираемся достичь этого в этой публикации!

Концепция

React - это фреймворк / библиотека представления (да, это долгое обсуждение), но здесь важно то, что его внимание уделяется компонентам сборки view. Давайте придерживаться оригинального React и применим наши примеры в Интернете, но эта концепция действительна для нативных и других разновидностей представлений React.

Голливудский принцип

Этот принцип связан с голливудским мышлением продюсерских домов, призывающих актеров на роли, а не наоборот:

«Не звоните нам, мы вам перезвоним»

В нашем (техническом) мире этот принцип говорит об инверсии управления во время выполнения. Позвольте мне объяснить это так, как вы поймете:

Да, React основан на этом. Кто вызывает «render» и другие методы жизненного цикла? Конечно, не так!

Вот почему React также рассматривается как фреймворк (предупреждение о полемическом обсуждении!), из-за этой инверсии управления во время выполнения он берет на себя ответственность за вызов того, что нужно вызвать в нужное время. Вам просто нужно реализовать правильные методы и вуаля!

Где там Duck Typing?

Голливудский принцип и Duck Typing тесно связаны. Если мы объединим эту инверсию управления, заставив этот «контроллер / оболочку» вызывать правильные методы, не импортируя экземпляр, а поведение, мы добьемся того, чего хотим.

Следуя этому принципу, давайте создадим пример чего-то довольно общего, в котором мы применим эти концепции простым способом:

Компонент Player Control

Давайте создадим простое управление проигрывателем с тремя кнопками: стоп, пауза и воспроизведение. Хитрость здесь в том, чтобы сделать его общим, используя оба принципа, которые мы обсуждали выше. Он должен контролировать то, что установлено внутри него (дочерние элементы), и не иметь значения для типа экземпляра, но он должен иметь три ожидаемых поведения: загрузка, пауза. и play (общий для медиаэлементов HTML):

Ничего нового, но если мы создадим Компонент, который действует так же, как медиа-элемент?

В нем есть все три метода, которые ожидает PlayerControl. А затем мы можем просто показать трех игроков в действии:

И это работает! Итак, это Duck Typing в действии. Пока он ведет себя так, как ожидает PlayerControl, он должен работать!

Проблема: использование ссылок

Можно использовать ссылки для медиа-элементов, но проблема в том, чтобы использовать для всего. Есть еще одна проблема: PlayerControl явно не объявляет, что ожидает от элементов этих трех методов (load, pause и play), что вызывает много путаница при его использовании. Если у вас есть тесты и документы, возможно, у вас меньше проблем с этим, но, как говорится в документации React:

«Избегайте использования ссылок для всего, что можно сделать декларативно.

Например, вместо того, чтобы раскрывать методы open() и close() в Dialogкомпоненте, передайте ему свойство isOpen ».

Решение: переверните столы!

Поскольку PlayerControl ожидает только мультимедийные элементы, ему просто не важен тип экземпляра (если это React Component или HTMLMediaElement) . Но давайте заставим PlayerControl предположить, что он получает Component, и если это не так, мы можем просто обернуть компонент, что-нибудь еще происходит внутри. Новый PlayerControl должен выглядеть так:

Как видите, он попытается внедрить три свойства в дочерний компонент. Если ребенок этого не ожидает, React предупредит вас. Теперь это намного больше похоже на «Реагировать», но теперь мы потеряли инверсию управления и поведенческие вызовы.

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

По сути, мы просто передали инверсию управления и Duck Typing в HOC. Вы можете вставить внутрь любой медиа-элемент (или Component с помощью этих методов, но мы этого избегаем), и он будет работать правильно.

Живой пример

Вы можете проверить исходный код и живой пример, чтобы убедиться, что он работает (с двумя обсуждаемыми концепциями: использование ссылок и HOC).

Заключение

Применить концепцию Duck Typing к React довольно сложно, но достижимо. Конечно, мы не можем использовать 100% шаблона, но мы можем адаптировать условия React для правильной работы (избегая использования refs).

Этот пример довольно прост, но его можно применить ко многим другим компонентам. Например, общий компонент «Мастер», который отображает этапы формул и ожидает, что они будут действительными, чтобы активировать кнопку «Далее». Другим примером могут быть виджеты на панели инструментов, где плагины могут иметь разные состояния просмотра (как конфигурация и визуализация), управляемые компонентом Widget, который их обертывает.

Modus Operandi всегда один и тот же, ожидайте, что дочерний компонент будет прослушивать некоторые свойства и что он будет реагировать на это.

Надеюсь, вам понравилась эта статья! Если вам действительно понравилось, покажите поддержку, хлопнув в ладоши 👏, это простой способ дать мне обратную связь!