Pull to refresh

Comments 12

Вместо наследования не очень наглядные решения вроде пользовательских хуков


Мне кажется это достаточно спорно звучит. Хуки это самое удобное что есть в реакте.

Я аж чаем поперхнулся. Жёсткие ограничения на места вызова хуков. Ручное указание всех зависимостей. Ререндер всего компонента, на изменение любого стейта. Намертво прибиты к реакту, без возможности переиспользования в других местах. Пляски с бубном для доступа к их состоянию вне рендеринга компонента.

Жесткое ограничение на вызовы: минус, согласен тут спорно, абстракция ради достижения цели, чаще всего интуитивная.

Ручное указание зависимостей: плюс, а вы пользовались когда-нибудь gdsfp в классовых компонентах с несколькими стейтами? Ручное указание зависимостей - гигантский скачок вперед для реакта после этого кошмара.

Рендер всего компонента на изменение стейта - выдуманный недостаток. А тут-то что не так? Классовые тоже перерендериваются при изменении стейта.

Намертво прибиты к реакту - тоже выдуманный пункт, классовые методы тоже прибиты к реакту, точнее даже к конкретному компоненту. Единственным способом переиспользования классовых методов жизненного цикла - является как раз написание HOC’ов. А вот хуки можно переиспользовать в других компонентах и даже хуках. В целом если встает проблема «прибитых к реакту хуков», то вероятно нет разграничения функциональности между утиллитами и хуками. Хуки должны реализовывать только части жизненного цикла компонентов.

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

Если уж надо назвать реальные минусы хуков - то это в первую очередь «казуальность». Хуки дают так много свободы, что комьюнити начала использовать хуки для решения проблемы здесь и сейчас, теряется грань между интерфейсами, размывается разграничение ответственностей - это все влечет за собой деградацию кодовой базы в руках слабых IT-специалистов.

Если чуть обобщить, то реакт никогда не славился следованием принципу «pit of success”, при котором самое логичное действие непременно приведет к успеху, а хуки в этом плане еще один шаг в противоположном направлении.

а вы пользовались когда-нибудь gdsfp в классовых компонентах с несколькими стейтами? Ручное указание зависимостей - гигантский скачок вперед для реакта после этого кошмара.

Откройте уже для себя любую из десятков библиотек с автоматическим отслеживанием зависимостей.

Классовые тоже перерендериваются при изменении стейта.

Только того, что находится в state, а не вообще всех полей объекта.

тоже выдуманный пункт, классовые методы тоже прибиты к реакту, точнее даже к конкретному компоненту

Объекты, лежащие в полях классового компонента, к реакту не прибиты.

Откройте уже для себя любую из десятков библиотек с автоматическим отслеживанием зависимостей.

Давайте не будем подменять понятия и от "ручного указания зависимостей" как недостаток функциональных компонентов перепрыгивать сразу к библиотекам стейт менеджеров. Стейт менеджеры уходят от изначальной проблемы и используются в любых компонентах, а статья и комментарии фокусируются на преимуществах и недостатках функциональных и классовых компонентов. Пример с gdsfp был как раз в качестве возможного способа управления зависимостями при получении новых состояний.

Только того, что находится в state, а не вообще всех полей объекта.

Возможно у вас другое определение слову "перерендеривается". В реакте перерендеринг - это процесс построения виртуального дерева на основе результата рендера компонента. Ни в классовых, ни в функциональных, нет ничего похожего на перерендеринг только того, что находится в state. Если под словом рендеринг вы подразумеваете "исполнение" тела функционального компонента, на другую чащу весов выставляя то, что классовый компонент не пересоздается, то я, вероятно, вас огорчу - это разные подходы к жизненному циклу, причем в случае функциональных компонентов тело все равно выполняется быстрее, а при корректно указанных зависимостях дополнительных побочных эффектов быть не должно. Что, кстати, в случае работы с несколькими состояниями в классовых компонентах - через тот же gdsfp становится настоящим адом, ведь он будет вызываться даже при изменении стейта.

Объекты, лежащие в полях классового компонента, к реакту не прибиты.

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

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

Единственным способом переиспользования классовых методов жизненного цикла - является как раз написание HOC’ов.

Я писал статью про другие способы, которые при желании можно применить и к классовым компонентам реакта: Техники повторного использования кода и разбиения сложных объектов на составные

HOC - это аналог паттерна "декоратор" для функциональных компонентов.

Хук - это аналог паттерна "стратегия" для функциональных компонентов. Только у функциональных компонентов недостаток в том, что в них нельзя заменить хук (стратегию), а в объектах/классах при использовании паттерна "стратегия", можно.

Намертво прибиты к реакту - тоже выдуманный пункт, классовые методы тоже прибиты к реакту, точнее даже к конкретному компоненту.

Классовые методы можно выносить в отдельные объект и переиспользовать в других компонентах. Просто из коробки нет общего подхода для такого переиспользования.

Касательно хуков. Группа хуков, вызов которых прописан в конкретном функциональном компоненте - это фиксированный список "стратегий". В геймдеве давно есть похожий подход, но применяемый к объектам/классам. Но там используется не фиксированный список, а динамический. Плюс более грамотное разделение ответственности. В реакте же компонент является и контейнером для стратегий (хуков), содержит в себе разметку, а также позволяет писать логику в самих компонентах. Такое объединение функционала является недостатком как функциональных, так и в классовых компонентах. Это нарушение принципа SRP, приводящее к уменьшение гибкости компонента и менее качественному коду пользователей react-а.

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

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

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

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

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

Про то, что хуки это исключительно стратегия не соглашусь

Я попытался показать, что механизмы расширения функционала при помощи паттерна стратегия и при помощи хуков довольно похожи. Абстрагируйтесь, не зацикливайтесь на ограничениях. Тогда станет заметно, что механизмы, применимые к функциям, можно применить к объектам, и наоборот.

Зачем возвращаться к устаревшему Реакту? Функциональные компоненты намного удобнее старых классовых.

Наследование в реакте - вершина антипаттернов, да и в целом это антипаттерн всего ООП при проектировании подобных сущностей.

Базовый принцип к которому аппелирует реакт - favor composition over inheritance. В остальном желание «Удобно расположить разные части кода по разным методам» - чаще всего тоже выстреливает в ногу. Когда в методах жизненного цикла появляется несколько цепочек не связанной напрямую функциональностей.

Забавный факт, но при переходе от классовых компонентов к функциональным, все проходят одну и ту же боль - нужно перестраивать мышление, с хуками возможно писать очень чистые и понятные компоненты, но для этого необходимо научиться выделять кастомные хуки. При этом возврат к классовым после полноценного перехода к хукам становится дорогой к громоздкому и грязному коду.

Все куда проще:

Когда «все» писали на C++, Java, .NET и Erlang из-за «нишевости», то «новые» языки чаще всего сваливались в мультипарадигму, как итог использовались для прототипирования

Никто не хотел доверять банковскую систему на Node.js и Django

Сейчас, в эпоху стартапов, где бизнес тестирует гипотезы, а банки — это очередной блокчейн, позволительно думать, что надо все писать на этом стеке, сравните качество систем.

А вот про стили написания на жабаскрипте:

— ООП кривое (наследование прототипное, где абстрактные классы? А зачем они, в погоне за хайпом .NET и жаба вводят реализацию в интерфейсы; полиморфизм, а где перегрузка методов? Инкапсуляция? Ой, а у нас hosting)

— ФП кривое (а где каррирование нормальное? А где пайп оператор? Библиотеку поставить? А не будет как с cross env? А где паттерн матчинг? А где атомы? А атомы есть, это символы, только пользоваться ими не умеют, лейблы используют чтобы из н^2 выйти

И я не говорю про отсутствие мультитрендинга и так далее

В общем, жабаскрипт — это все еще прототипирование, спорить о парадигмах в нем глупо, так как его задача — гипотезы и стартапы, хотя у Амазона с лямбдами есть свои плюсы.

Писать нужно в код-стайле команды и хороших практик. Половина паттернов не пригодны, SOLID не реализуется.

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

И как говорят классики — выстраивать карьеру возле одной библиотеки для языка прототипов — это вилы

Привет, Event Loop

Sign up to leave a comment.

Articles