Хуки — это просто
Хуки — это технология перехвата вызовов функций в чужих процессах. Хуки, как и любая достаточно мощная технология, могут быть использованы как в благих целях (снифферы, аудио\видеограбберы, расширения функционала закрытого ПО, логирование, багфиксинг) так и со злым умыслом (трояны, кряки, кейлоггеры). О хуках уже не раз писали и на Хабре и не на Хабре. Но вот в чём беда — почему-то каждая статья о хуках буквально со второго абзаца начинает рассказывать о «таблице виртуальных функций», «архитектуре памяти» и предлагает к изучению огромные блоки ассемблерного кода. Известно, что каждая формула в тексте снижает количество читателей вдвое, а уж такие вещи — так и вовсе вчетверо. Поэтому нужна статья, которая расскажет о хуках просто. Под катом нет ассемблера, нет сложных терминов и буквально два десятка строк очень простого кода на С++. Если вы давно хотели изучить хуки, но не знали с чего начать — начните с этой статьи.
Реальная задача
Для лучшего понимания того, что мы делаем — поставим себе какую-нибудь реальную задачу. Давайте, например сделаем так, чтобы браузер Firefox при заходе на Хабр писал в своём заголовке «Привет, Хабр!» вместо того, что там пишется сейчас (а сейчас там пришется «*** / Хабрахабр — Mozilla Firefox», где *** — меняется в зависимости от раздела). Да, я знаю, что это можно сделать правкой исходников Firefox, браузерными плагинами, юзерскриптами и еще десятком способов. Но мы в учебных целях сделаем это хуками.
Совсем чуть-чуть теории
Когда Вы запускаете любое приложение — операционная система создаёт его процесс. Грубо говоря, exe-файл копируется в память, далее определяется какие именно библиотеки (dll-файлы) ему нужны для работы (эта информация записана в начале каждого exe-файла), эти библиотеки ищутся (в папке с программой и в системных папках) и загружаются в память процесса. Потом определяется, какие именно функции библиотек использует программа и где они находятся (в какой библиотеке и где именно в этой библиотеке). Строится табличка вида «функция SomeFunction1() — библиотека SomeLibrary1.dll — %адрес_функции_SomeFunction1()%». Когда программе понадобиться вызвать эту функцию — она найдет в своей памяти нужную библиотеку, отсчитает нужный адрес и передаст туда управление.
Суть хукинга — заставить программу поверить, что нужная ей функция находится в другом месте.
Делается это таким образом — мы пишем свою библиотеку SomeLibrary2.dll, в которой будет находится наша функция SomeFunction2(). Далее мы загружаем эту библиотеку в память чужого процесса (в ОС Windows есть специальная функция для этого) и изменяем ту самую табличку, о которой я писал чуть выше, так, чтобы теперь она содержала запись «функция SomeFunction1() — библиотека SomeLibrary2.dll — %адрес_нашей_функции_SomeFunction2()%». Для того, чтобы понять, как вручную сделать всё описанное в этом абзаце, нужно знать весьма прилично всего — как устроена память в Windows, как вызываются функции, как им передаются аргументы и т.д. Это сложно. Ну на самом деле не очень, просто можно обойтись и без этого. Если вам это нужно — почитайте какую-нибудь продвинутую статью (а хоть бы из тех, что указаны в начале). Мы пойдем другим путем — используем готовую библиотеку Microsoft Detours, которая сделает всю грязную работу за нас.
Пару слов о Microsoft Detours
Проста в изучении и использовании
Весьма эффективна
Хорошая документация
Содержит много примеров в исходниках
Разработана Microsoft — неплохо «дружит» с ОС
Бесплатна для исследовательских целей и некоммерческих проектов
Не требует знания ассемблера
Закрыта
Стоит приличных денег для коммерческого использования или х64-архитектуры
В целом, я бы посоветовал начинать изучение хуков именно с Detours — если это будет всего лишь вашим разовым развлечением, то этого вполне хватит, у вас быстро всё получится и вам понравится. Если же хуки понадобятся в серьёзном проекте — вы легко переключитесь на бесплатные и открытые (но чуть более сложные) библиотеки типа mhook, купите Detours или напишете свой велосипед (для последних двух решений нужны весьма веские причины).
О том где взять и как собрать Detours я писал вот тут.
Хитрый план
Куда ставить хук
Переходим в Firefox, открываем Хабр, дожидаемся изменения заголовка на нужный и возвращаемся в Api Monitor чтобы остановить мониторинг. Скорее всего, вы будете удивлены количеством вызванных функций — их могут быть сотни тысяч буквально за несколько секунд мониторинга. А мы ведь еще и следим далеко не за всем. Да-да, это всё реально происходит внутри безобидного открытия всего одного сайта в браузере! А вы еще жалуетесь, что эта пара секунд — слишком долго.
Найти нужную нам функцию поможет поиск по вкладке с результатами мониторинга. Вбиваем в поиск «WM_SETTEXT» и убеждаемся, что действительно имеются вызовы функции SendMessageW с этим параметром — с высокой вероятностью это и есть установка заголовка окна. Обратите внимание на «W» в конце названия функции — оно означает, что используется её юникодная версия. Для установки хуков важно знать точное имя подменяемой функции и теперь мы его знаем.
Делаем свою библиотеку
4. Открываем свойства проекта и на вкладке настроек линкера добавляем в поле Additional Dependencies значение «C:\Program Files\Microsoft Research\Detours Express 3.0\lib.X86\detours.lib». Внимание, у вас путь может быть другой — смотря куда установили библиотеку Detours.
Давайте разберем исходник. В начале мы подключаем заголовочные файлы Windows (чтобы пользоваться функцией SendMessageW) и Detours (чтобы иметь возможность ставить\снимать хуки).
В сложной на первый взгляд строке №3 мы всего лишь сохраняем реальный указатель на функцию SendMessageW в переменную TrueSendMessageW. Это нам понадобиться для двух целей:
Функция DllMain вызывается операционной системой в определенных случаях — например, в моменты аттача\детача библиотеки к процессу. Тут тоже всё просто. В момент аттача нам нужно установить хуки, в момент детача — снять. Библиотека Detour требует делать это транзакциями, и в этом есть смысл — представьте себе что будет, если сразу несколько желающих захотят поставить хуки в один процесс. Самое важное в этом коде это строка
Именно она заставляет процесс «поверить» что теперь вместо настоящей функции SendMessageW нужно вызывать нашу MySendMessageW. Ради этой строки всё и затевалось. Если кому интересно, однажды я писал аналог этой функции вручную. С учетом всех возможных комбинаций типов функций и архитектур это заняло у меня несколько недель. Вы вот только что их сэкономили — поздравляю.
Windows hook: просто о сложном
Что такое хук?
Что такое хук функций и для чего он нужен? В переводе с английского «hook» — ловушка. Поэтому о назначении хуков функции в Windows можно догадаться — это ловушка для функции. Иными словами, мы ловим функцию и берем управление на себя. После этого определения нам открываются заманчивые перспективы: мы можем перехватить вызов любой функции, подменить код на свой, тем самым изменив поведение любой программы на то, которое нам нужно (конечно, в рамках определенных ограничений).
Целью данной статьи является демонстрация установки хука и его непосредственная реализация.
— Нельзя поверить в невозможное!
— Просто у тебя мало опыта, – заметила Королева. – В твоем возрасте я уделяла этому полчаса каждый день! В иные дни я успевала поверить в десяток невозможностей до завтрака!
Где мне реально пригодились эти знания
Эти знания являются очень узкоспециализированными, и в повседневной практике разработки маловероятно, что они пригодятся, но знать о них, на мой взгляд, крайне желательно, даже если эти знания чисто теоретические. На моей практики же мне пригодились эти знания для решения следующих задач:
• Контроль входящего http-траффика и подмена «взрослого» контента на более безобидный.
• Логирование информации в случае копирования каких-либо файлов с подконтрольной сетевой папки.
• Незначительная модификация кода в проекте, от которого были утеряны исходники (да, и такое тоже случается)
Методы установки хуков
Давайте перейдем от общих фраз к более детальному рассмотрению хуков. Мне известно несколько разновидностей реализации хука:
● Использование функции SetWindowsHookEx. Это весьма простой, оттого и ограниченный, метод. Он позволяет перехватывать только определенные функции, в основном связанные с окном (например, перехват событий, которые получает окно, щелчков мышкой, клавиатурного ввода). Достоинством этого метода является возможность установки глобальных хуков (например, сразу на все приложениях перехватывать клавиатурный ввод).
● Использование подмены адресов в разделе импорта DLL. Суть метода заключается в том, что любой модуль имеет раздел импорта, в котором перечислены все используемые в нем другие модули, а также адреса в памяти для экспортируемых этим модулем функций. Нужно подменить адрес в этом модуле на свой и управление будет передано по указанному адресу.
● Использование ключа реестра HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Windows\AppInit_Dlls. В нем необходимо прописать путь к DLL, но сделать это могут только пользователи с правами администратора. Этот метод хорош, если приложение не использует kernel32.dll (нельзя вызвать функцию LoadLibrary).
● Использование инъектирования DLL в процесс. На мой взгляд, это самый гибкий и самый показательный способ. Его-то мы и рассмотрим более подробно.
Инъектирование возможно, потому что функция ThreadStart, которая передается функции CreateThread, имеет схожую сигнатуру с функцией LoadLibrary (да и вообще структура dll и исполняемого файла очень схожи). Это позволяет указать метод LoadLibrary в качестве аргумента при создании потока.
Алгоритм инъектирования DLL выглядит так:
1. Находим адрес функции LoadLibrary из Kernel32.dll для потока, куда мы хотим инжектировать DLL.
2. Выделяем память для записи аргументов этой функции.
3. Создаем поток и в качестве ThreadStart функции указываем LoadLibrary и ее аргумент.
4. Поток идет на исполнение, загружает библиотеку и завершается.
5. Наша библиотека инъектирована в адресное пространство постороннего потока. При этом при загрузке DLL будет вызван метод DllMain с флагом PROCESS_ATTACH. Это как раз то место, где можно установить хуки на нужные функции. Далее рассмотрим саму установку хука.
Подход, используемый при установке хука, можно разбить на следующие составные части:
1. Находим адрес функции, вызов которой мы хотим перехватывать (например, MessageBox в user32.dll).
2. Сохраняем несколько первых байтов этой функции в другом участке памяти.
3. На их место вставим машинную команду JUMP для перехода по адресу подставной функции. Естественно, сигнатура функции должна быть такой же, как и исходной, т. е. все параметры, возвращаемое значение и правила вызова должны совпадать.
4. Теперь, когда поток вызовет перехватываемую функцию, команда JUMP перенаправит его к нашей функции. На этом этапе мы можем выполнить любой нужный код.
Далее можно снять ловушку, вернув первые байты из п.2 на место.
Итак, теперь нам понятно, как внедрить нужную нам DLL в адресное пространство потока и каким образом установить хук на функцию. Теперь попробуем совместить эти подходы на практике.
Наше тестовое приложение будет довольно простым и написано на С#. Оно будет содержать в себе кнопку для показа MessageBox. Для примера, установим хук именно на эту функцию. Код тестового приложения:
В качестве инъектора рассмотрим два варианта. Инъекторы, написанные на С++ и С#. Почему на двух языках? Дело в том, что многие считают, что С# — это язык, в котором нельзя использовать системные вещи, — это миф, можно :). Итак, код инъектора на С++:
Теперь тоже самое, но только на С#. Оцените, насколько код более компактен, нет буйства типов (HANDLE, LPVOID, HMODULE, DWORD, которые, по сути, означают одно и тоже).
Теперь самое интересное — код библиотеки, которая устанавливает хуки. Эта библиотека написана на С++, пока без аналога на C#.
Ну и несколько картинок напоследок. До установки хука:
В следующем нашей материале мы постараемся написать код библиотеки, которая устанавливает хуки на C#, т. к. механизм инъектирования управляемого кода заслуживает отдельной статьи.
Хуки в PHP, принцип работы
При разработки масштабируемых приложений часто применяют хуки в PHP. Кому-то хуки нравятся, кому-то нет, но так или иначе с ними приходится иметь дело и проблема в том, что не все понимают, как это работает.
В данной статье я расскажу принцип — как работают хуки в PHP. Использовать хуки можно в любом веб-приложении, например тот, кто работает с WordPress постоянно с ними сталкивается. Использование хуков дает гибкость приложению и позволяет сторонним разработчикам расширять функционал без вмешательства в основной код.
Рассмотрим простой пример
Есть HTML шаблон и он уже заверстан. Предположим, что по каким-то причинам нельзя вмешиваться в код шаблона и что-либо менять, но при этом есть необходимость дополнить его данными.
Чаще всего возникает необходимость дополнить HTML шаблон мета-тегами, стилями, скриптами в шапке или в подвале.
Пусть существует следующий шаблон страницы:
Чтобы дать возможность добавлять мета-теги, стили и скрипты, разработчику необходимо снабдить шаблон хуками и добавить функции обработки. По сути, хуки — это крючки, за которые можно зацепиться, то есть идентифицировать то место, в котором необходимо произвести какое-либо дополнительное действие.
Код приобретет следующий вид:
Как do_action узнает какие функции нужно выполнить
В действительности все названия функций, которые должны быть выполнены на определенном хуке хранятся в массиве. Переменная, содержащая этот массив, является глобальной и доступна во всем приложении, следовательно мы можем дописывать данные в эту переменную.
Пусть массив имеет следующий вид:
Получается, что есть списки, которые складываются в один большой список, где hook_name_x — это название какого-то хука, index_x_x — индекс(порядковый номер) функции function_name_x_x в списке указанного хука.
При этом порядковый номер функции в списке можно использовать для определения последовательности выполнения функций — чем больше значение индекса, тем ниже эта функция будет в списке, а значит тем позже она будет выполнена.
Все это можно объяснить на примере: представьте себе человека, который спускается на лифте и у него в руках тетрадь, каждая страница которой соответствует какому-либо этажу, на котором останавливается лифт, на каждой странице имеется список задач, которые следует выполнить на соответствующем этаже. В данном примере названия этажей являются хуками, а элементы списка(задачи) на каждой странице, являются функциями, привязанными к конкретному хуку. Очередность выполнения задач определяется их положением в списке, сверху вниз.
Привязка функции к хуку
Для того, чтобы указать по какому хуку следует выполнить функцию, необходимо добавить название функции в соответствующий список. При этом должна быть возможность указать приоритет выполнения функции.
Хуки — это лучшее, что случилось с React
React — это самая популярная фронтенд-библиотека из экосистемы JavaScript. Она известна простотой использования и читабельностью кода, создаваемого с её применением. Это позволяет организациям самых разных масштабов успешно внедрять данную библиотеку. Но компоненты, основанные на классах, это громоздкие конструкции, с которыми непросто разобраться. Хуки позволяют работать с состоянием компонентов, с методами их жизненного цикла, с другими механизмами React без использования классов.
В этой статье мы поговорим о том, что такое React-хуки, о том, что отличает их от других механизмов библиотеки, и о том, почему они — это лучшее, что случилось с React.
О возникновении хуков React
Изначально в библиотеке React использовались, в основном, компоненты, основанные на классах. Применение таких компонентов может потребовать приложения чрезмерных усилий в ходе разработки, так как программисту постоянно приходится переключаться между классами, компонентами высшего порядка, свойствами рендеринга. А с появлением хуков React можно, решая те же задачи, что и раньше, не переключаясь между различными механизмами, просто пользоваться функциональными компонентами. Хуки значительно улучшили React из-за того, что с их помощью можно писать код, который получается проще, чем код, который писали раньше, но при этом позволяет быстрее и эффективнее реализовывать похожий функционал. А ещё можно, не пользуясь классами, работать с состоянием компонентов и с методами их жизненного цикла.
Вот примеры кода, иллюстрирующие использование компонентов, основанных на классах, и функциональных компонентов.
Компонент, основанный на классах:
Этот компонент выводит в DOM элемент
А вот — код функционального компонента, решающего ту же задачу.
Да, обратите внимание на то, что хуки нельзя использовать в компонентах, основанных на классах.
Как хуки упрощают работу с методами жизненного цикла компонентов?
Среди методов жизненного цикла React-компонента можно отметить те, которые вызываются при его монтировании, обновлении и размонтировании.
Изначально эти методы можно было использовать только при применении компонентов, основанных на классах. Это обычно было связано с необходимостью работать с кодом, который достаточно сложно писать и читать. Если же пользоваться функциональными компонентами и хуками — решение тех же задач упрощается.
Предположим, нам нужно загрузить данные с использованием метода жизненного цикла componentDidMount() в компоненте, основанном на классах:
А теперь решим ту же задачу в функциональном компоненте, пользуясь хуками useState и useEffect :
Хуки облегчили изучение React
Компоненты, основанные на классах, всегда были несколько громоздкими и непонятными конструкциями, особенно учитывая то, что их применение ведёт к тому, что механизмы управления состоянием компонента и многократного использования кода кажутся сложнее, чем они есть на самом деле. Это привело к тому, что многие новички избегали React, выбирая более «лёгкие» библиотеки и фреймворки. А с появлением хуков изучить React стало легче, чем прежде. Это стало одной из причин роста популярности React.
На этом графике виден постоянный рост интереса к React на Stack Overflow, продолжающийся уже много лет. Здесь же можно сравнить процент вопросов о React с процентом вопросов о других популярных JavaScript-инструментах. Этот график доказывает то, что разработчики стали чаще пользоваться библиотекой React после появления хуков.
О некоторых хуках и их предназначении
▍Хук useState
Вероятно, useState — это самый распространённый React-хук. Он позволяет работать с переменными состояния в функциональных компонентах.
Здесь useState принимает единственный аргумент: исходное значение состояния. Он возвращает массив с переменной state и с функцией для обновления этого состояния. После этого у программиста есть всё, что нужно для работы с состоянием в функциональном компоненте.
▍Хук useEffect
Хук useEffect помогает программисту выполнять побочные эффекты в функциональных компонентах. То есть — вызывать функции, которые нужно выполнить после обновления DOM. Он заменяет некоторые события, позволяя вызывать функцию при изменении одной или нескольких переменных. Он принимает два аргумента: функцию и необязательный массив. Эта функция определяет то, какой именно «побочный эффект» нужно выполнить, а в массиве указывают переменные, за изменениями которых нужно наблюдать.
▍Другие хуки
Итоги
Мы, при создании React-компонентов, пользовались классами из-за того, что в своё время для работы с состоянием или для реализации методов жизненного цикла нельзя было воспользоваться функциональными компонентами. Хуки React значительно упростили решение старых задач, дав нам возможность писать код, который отличается лучшей пригодностью к созданию нового функционала методом композиции, который получается гибче, чем прежде, который легче расширять. Многие компании используют React в роли своей основной фронтенд-библиотеки, что приводит к тому, что всё больше и больше разработчиков осваивают React.
Пользуетесь ли вы хуками React в своих проектах?
Введение в хуки
Хуки — нововведение в React 16.8, которое позволяет использовать состояние и другие возможности React без написания классов.
Вы можете начать изучать хуки на следующей странице. Здесь же мы расскажем, зачем мы добавили хуки в React, и как они помогут вам писать приложения.
React 16.8.0 это первый релиз, поддерживающий хуки. При обновлении версии, не забудьте обновить и все зависимости, включая React DOM. Поддержка хуков в React Native появилась в версии 0.59.
На конференции React Conf 2018, Софи Алперт (Sophie Alpert) и Дэн Абрамов (Dan Abramov) представили хуки, а Райн Флоренс (Ryan Florence) показал, как их использовать в приложении. Видео конференции можно посмотреть здесь:
Полная обратная совместимость
Перед тем, как мы продолжим, обратите внимание, что хуки:
Мы не планируем удалять классы из React. Вы можете прочитать больше о стратегии постепенного внедрения хуков в разделе ниже.
Хуки не меняют ваши знания о концепциях в React. Вместо этого, хуки предоставляют более прямой доступ к API уже знакомых вам понятий: пропсов, состояния, контекста, рефов, и жизненного цикла. Мы также рассмотрим мощный способ компоновать эти понятия с помощью хуков.
Чтобы начать изучать хуки, перейдите на следующую страницу! На этой странице мы расскажем о том, зачем нужны хуки, и как их использовать, не переписывая наши приложения.
Хуки решают множество, казалось бы, несвязанных между собой, проблем в React, с которыми мы сталкивались в течение пяти лет написания и поддержки десятков тысяч компонентов. Если вы изучаете React, используете его ежедневно или используете другую библиотеку с похожим компонентным подходом, эти проблемы наверняка покажутся вам знакомыми.
Трудно повторно использовать логику состояний между компонентами
В React нет способа «присоединить» повторно используемое поведение к компоненту (например, подключение к хранилищу). Если вы работали с React какое-то время, то вам могут быть знакомы такие паттерны, как рендер-пропсы и компоненты высшего порядка, которые пытаются решить эту проблему. Но эти паттерны заставляют вас изменять структуру компонентов, что делает код громоздким и трудным в поддержке. Если вы посмотрите на типичное React-приложение в React DevTools, то увидите «ад обёрток» из компонентов, окружённых провайдерами, консьюмерами, компонентами высшего порядка, рендер-пропсами и другими абстракциями. Хоть мы и можем отфильтровать их в DevTools, всё это указывает на более глубокую проблему в React. Нужен более удобный способ повторно использовать логику вокруг состояния.
С помощью хуков вы можете извлечь логику состояния из компонента, чтобы её протестировать или повторно использовать. Хуки позволяют вам повторно использовать логику состояния, не затрагивая дерево компонентов. Благодаря этому, хуки легко использовать в разных компонентах и делиться ими с сообществом.
Мы обсудим это подробнее в разделе Создание собственных хуков.
Сложные компоненты становятся трудными для понимания
В некоторых случаях невозможно разбить компоненты на более мелкие, потому что логика состояния раскидана повсюду. Такие компоненты сложно тестировать. Это одна из причин, по которой люди предпочитают использовать в React отдельную библиотеку для управления состоянием. Однако, это добавляет множество абстракций, заставляет прыгать между разными файлами и усложняет повторное использование компонентов.
Чтобы решить эту проблему, хуки позволяют разбить один компонент на маленькие функции по их назначению (например, подписке или загрузке данных), а не на основе методов жизненного цикла. Вы также можете контролировать внутреннее состояние с помощью редюсера, чтобы поведение было более предсказуемым.
Классы путают как людей, так и машины
Вдобавок к усложнению организации кода и его повторного использования, классы создают существенный барьер в изучении React. Нужно понимать, как работает this в JavaScript, поведение которого отличается от большинства языков. Приходится помнить про привязку контекста для обработчиков событий. Без использования нестабильных синтаксических предложений, код становится многословным. Люди могут прекрасно понимать пропсы, состояние и однонаправленный поток данных, но всё равно путаться с классами. Различия между функциональными и классовыми компонентами в React и тем, когда их использовать, приводят к разногласиям даже между опытными React-разработчиками.
Вдобавок, React существует уже около пяти лет и мы хотим убедиться, что он останется актуальным в течение следующих пяти лет. Как показывают Svelte, Angular, Glimmer и другие технологии, компиляция компонентов перед их исполнением имеет огромный потенциал в будущем. Особенно, если шаблоны не накладывают ограничений. Недавно мы экспериментировали со свёртыванием компонентов с использованием Prepack и увидели первые многообещающие результаты. Однако мы заметили, что классовые компоненты могут приводить к ненамеренным паттернам, сводящим оптимизации на нет. Классы создают сложности для инструментов и сегодня. Например, классы плохо минифицируются, а горячая перезагрузка (hot reloading) ненадёжна и часто ломает их. Наша цель — предоставить API, который повысит вероятность того, что код можно будет оптимизировать.
Чтобы решить эти проблемы, хуки позволяют использовать больше возможностей React без написания классов. Концептуально, React-компоненты всегда были ближе к функциям. Хуки обеспечивают доступ к функционалу, но не обесценивают опыт использования React. Хуки предоставляют императивные лазейки и не требуют от вас изучения сложных функциональных или реактивных подходов.
Обзор хуков — хорошее начало для изучения хуков.
Стратегия постепенного внедрения
TLDR: Мы не планируем удалять классы из React.
Мы знаем, что React-разработчики сфокусированы на поставке продукта и у них нет времени изучать новый API каждого релиза. Хуки это что-то новое, и возможно, лучше подождать больше примеров и уроков, прежде чем начинать их изучение.
Мы также понимаем, что планка для добавления новых примитивов в React очень высока. Поэтому для любопытных читателей мы подготовили подробный RFC, в котором можно найти больше информации о технических аспектах выбранного дизайна.
Важно понимать, что хуки работают рядом с существующим кодом, поэтому вы можете внедрять их постепенно. Нет спешки переходить на хуки. Мы рекомендуем избегать любых «больших переписываний», особенно для существующих, сложных классовых компонентов. Вам потребуется немного изменить мировоззрение, чтобы начать «мыслить хуками». По нашему опыту, лучше всего сначала попрактиковаться использовать хуки в новых и некритичных компонентах и убедиться, что все в вашей команде чувствуют себя комфортно с ними. После того, как вы попробуете, не стесняйтесь отправить нам свой отзыв, позитивный или негативный.
Мы намерены охватить все возможные варианты использования классов в хуках, но мы всё ещё будем поддерживать классовые компоненты в обозримом будущем. В Facebook десятки тысяч компонентов, написанных в виде классов, и у нас нет абсолютно никаких планов их переписывать. Вместо этого мы начинаем использовать хуки в новом коде параллельно с классами.
Часто задаваемые вопросы
Мы подготовили для вас страницу FAQ с ответами на самые частые вопросы о хуках.
К концу этой страницы вы должны иметь общее представление о том, какие проблемы решают хуки, но многие детали, возможно, остались непонятны. Не беспокойтесь! Давайте перейдём на следующую страницу, где мы изучим хуки на примерах.