Как написать статью о React Hooks, когда их так много уже опубликовано? Это вопрос, который я задал себе перед тем, как начать этот. Я почти отказался от этой идеи, но наконец нашел кучу веских причин продолжить:

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

Поэтому я просто начну эту статью, учитывая, что вы знаете основы React, но ничего не знаете о хуках.

Реагируйте по последнему слову техники до появления крючков

Существует два основных способа создания компонента React: путем создания класса или функции.

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

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

Чтобы иметь полный контроль, вам нужно было преобразовать свой компонент в версию класса.

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

Компоненты высшего порядка (HoC)

В сообществе React возникла закономерность. Сейчас он очень распространен и, на удивление, не имеет аналогов в других фреймворках: HoC.

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

Этот шаблон быстро распространился, и существует несколько библиотек с открытым исходным кодом, которые в основном полагаются на HoC для получения доступа к хранилищу Redux, внедрения данных GraphQL, получения перевода i18n и т. Д.

У этого паттерна много преимуществ:

  • Ваши собственные компоненты могут оставаться простыми, чаще всего они могут быть функциональными компонентами.
  • Каждую функцию, которую использует ваш компонент, можно легко идентифицировать. Его даже можно разделить между несколькими компонентами.

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

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

Но у HoC есть реальные недостатки, которые вы должны понимать:

  • Понять концепцию инкапсуляции компонентов непросто. Мне все еще нужен момент для размышлений, когда я пишу его с нуля.
  • Инкапсуляция 2, 4, иногда 6 или 8 компонентов вокруг одного, который вы написали, снижает производительность, это факт. Это может быть не тяжело, но это правда.
  • HoC действительно делает вашу панель отладки похожей на беспорядок. Это заставляет меня вспомнить темные дни ада обратных вызовов JavaScript!

Крючки!

Ух, наконец-то основная тема! Я хотел объяснить контекст использования в сообществе React, чтобы понять, какие проблемы пытаются решить хуки. Готово!

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

Это прямая цитата из официального анонса релиза React 16.8.0, который содержит хуки (да, они уже выпущены!)

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

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

Есть 3 основных, которые легко запомнить:

  • useState для объявления новой переменной состояния для компонента
  • useEffect для взаимодействия с жизненным циклом компонента
  • useContext для получения значения контекста

Полный API можно найти в официальной документации React.

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

Для меня, как для пользователя Recompose, хуки сделали одну из моих любимых библиотек совершенно бесполезной, но какой лучший конец могла бы иметь библиотека, кроме обобщения концепции непосредственно в структуре, которую она пыталась заполнить?

Тем, кого беспокоит сама Recompose, вы должны знать, что создатель Эндрю Кларк теперь входит в основную команду React, он сам работал над кодированием хуков и «официально заявил, что это суждено быть заброшенный". Большое ему дело!

На данный момент не сказано, что крючки полностью совместимы с ретро. Компоненты классов по-прежнему работают, как и раньше, HoC тоже работает. Команда ядра React даже не советует разработчикам агрессивно преобразовывать свои кодовые базы (именно этого я не буду делать 😇), а скорее советует привыкнуть к нему на нескольких новых компонентах, прежде чем рассматривать возможность рефакторинга старых.

Почему это так интересно?

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

Тем не менее, я думаю, что это хорошее упражнение, чтобы подвести их итоги. Давайте представим, как будет выглядеть мир React, полный хуков (я почти уверен, что сообщество будет склонно их широко применять):

  • Конец сегментации между функциональными и классовыми компонентами, по крайней мере, в одном проекте. Функциональные компоненты и компоненты класса становятся личным выбором стиля, точно так же, как пробел вместо отступа табуляции или конечной запятой ...
  • Отказ от HoC для снижения сложности, снижения производительности и запутывания отладки.
  • Если больше нет класса, больше нет this 🎉.
  • Поскольку логика компонентов теперь представляет собой просто вызовы функций, ее можно извлекать в другие файлы, совместно использовать, повторно использовать и тестировать гораздо лучше, чем раньше.

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

Как это работает (примерно)

С точки зрения пользователя, вы просто вызываете use** функции из своего функционального компонента, и все. Но как это может быть возможным или даже эффективным, если вы знаете, что эта функция компонента будет вызываться при каждом обнаружении изменений?

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

Крючки - это не стандартные функции.

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

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

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

Массив хуков позволяет React сопоставлять предыдущий вызов со следующим из того же хука, и это объясняет, почему существует правило о сумме и порядке. Эта реализация может быть (и обсуждалась), но основная команда React пришла к выводу, что это лучший выбор, учитывая несколько решений, как Дэн Абрамов хорошо объяснил.

Более глобально, поскольку хуки нельзя вызывать откуда угодно, в любом порядке, в любое время и т. Д .:

Крючки по своей конструкции небезопасны.

Это жертва, на которую пошла команда React, предоставив очень простой API для подавляющего большинства.

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

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

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

Напишем зацепки!

Это была довольно длинная статья, но мы почти не коснулись ее темы. Использование хуков (и только хуков) во всем приложении вызывает намного больше вопросов.

Поэтому это только первая, немного теоретическая, статья на эту тему. Я планировал написать другие во время собственного процесса перехода на хуки.

В качестве скромного захватчика я собирался рассказать в следующих статьях следующее:

  • Хуки в сторонних фреймворках (в начале 2019 года)
  • Примеры разделения логики между компонентами
  • Сравнение Recompose и хуков
  • Хуки и SSR с Next
  • Тестирование пользовательских хуков и компонентов с помощью хуков