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 с ответами на самые частые вопросы о хуках.

К концу этой страницы вы должны иметь общее представление о том, какие проблемы решают хуки, но многие детали, возможно, остались непонятны. Не беспокойтесь! Давайте перейдём на следующую страницу, где мы изучим хуки на примерах.

Источник

Хуки — это лучшее, что случилось с React

React — это самая популярная фронтенд-библиотека из экосистемы JavaScript. Она известна простотой использования и читабельностью кода, создаваемого с её применением. Это позволяет организациям самых разных масштабов успешно внедрять данную библиотеку. Но компоненты, основанные на классах, это громоздкие конструкции, с которыми непросто разобраться. Хуки позволяют работать с состоянием компонентов, с методами их жизненного цикла, с другими механизмами React без использования классов.

React хуки что это. . React хуки что это фото. React хуки что это-. картинка 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 hooks — победа или поражение?

React хуки что это. . React хуки что это фото. React хуки что это-. картинка React хуки что это. картинка

С выходом нового React 16.6.0 в документации появился HOOKS (PROPOSAL). Они сейчас доступны в react 17.0.0-alpha и обсуждаются в открытом RFC: React Hooks. Давайте разберемся что это такое и зачем это нужно под катом.

Да это RFC и вы можете повлиять на конечную реализацию обсуждая с создателями react почему они выбрали тот или иной подход.

Давайте взглянем на то как выглядит стандартный хук:

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

Как уверяют ребята, это не план по выпиливанию классов из реакта.

Так же хуки не заменяют текущие концепции реакта, все на месте props/state/context/refs. Это всего лишь еще один способ использовать их силу.

Мотивация

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

Самое сложное это переиспользовать логику в stateful компонентах, у реакта нет способа прикрепить многоразовое поведение к компоненту(например подключить его к хранилищу). Если вы работали с React вам известно понятие HOC(high-order-component) или render props. Это достаточно хорошие паттерны, но иногда они используются чрезмерно, они требуют реструктуризации компонентов, для того, чтобы их можно было использовать, что обычно делает код более громоздким. Стоит посмотреть на типичное реакт приложение и станет понятно о чем идет речь.

React хуки что это. image loader. React хуки что это фото. React хуки что это-image loader. картинка React хуки что это. картинка image loader

Это называется wrapped-hell — ад оберток.

Приложение из одних HOC это нормально в текущих реалиях, подключили компонент к стору/теме/локализации/кастомным хокам, я думаю это всем знакомо.

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

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

Классы сложны для людей и для машин

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

Глянем на хуки

State hook

Код ниже рендерит параграф и кнопку и если мы нажмем на кнопку то значение в параграфе будет инкрементировано.

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

Effect hook

Часто в классовых компонентах, мы делаем side effect функции, например подписываемся на события или делаем запросы за данными, обычно для этого мы используем методы componentDidMount / componentDidUpdate

Когда мы вызываем useEffect мы говорим реакту сделать ‘side effect’ после обновления изменений в DOM дереве. Эффекты объявляются внутри компонента, поэтому имеют доступ к props/state. Причем их мы можем точно так же создавать сколько угодно.

Сразу же стоит обратить внимание на второй side effect в нем мы возвращаем функцию, делаем мы это для того, чтобы выполнить какие то действия после того как компонент выполняет unmount, в новом api это называют эффекты с очисткой. Остальные эффекты могут возвращать, что угодно.

Правила хуков

Хуки это просто javascript функции, но они требуют всего двух правил:

Кастомные хуки

В тоже время нам хочется переиспользовать логику stateful компонентов, обычно для этого используют либо HOC либо render props паттерны, но они создают дополнительный объем нашего приложения.
Например опишем следующую функцию:

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

В любом случае, мы переиспользуем состояние компонента, каждый вызов функции useFriendStatus создает изолированное состояние. Так же стоит отметить, что начало этой функции начинается со слова use это говорит о том, что это хук. Советуем соблюдать этот формат. Вы можете писать кастомные хуки на что угодно, анимации/подписки/таймеры и много многое другое.

Есть еще пара хуков.

useContext

useContext позволяет использовать вместо renderProps обычное возвращаемое значение, в него следует передать контекст который мы хотим извлечь и он нам его вернет, таким образом мы можем избавиться от всех HOC, которые передавали context в props.

И теперь объект контекста мы можем просто использовать в возвращаемом значении.

useCallback

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

useMemo

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

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

useRef

useImperativeMethods

useImperativeMethods кастомизирует значение экземпляра который передается из родителя и использует ref напрямую. Как всегда следует избегать передачу ссылок на прямую и следует использовать forwardRef

useMutationEffect

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

useLayoutEffect

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

useReducer

useReducer — это хук для создания редюсера который возвращает состояние и возможность диспатчить изменения:

Так же useReducer принимает 3 аргумент, это action который должен выполнятся при инициализации редюсера:

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

Подводя итог

Хуки достаточно мощный подход по решению wrapper-hell и решают несколько проблем, но все их можно свети с одному определению передача ссылок. Уже сейчас начинают появляться сборники хуков по использованию или этот сборник. Более подробнее с хуками можно познакомиться в документации.

Источник

Хуки: ответы на вопросы

Хуки — нововведение в React 16.8, которое позволяет использовать состояние и другие возможности React без написания классов.

На этой странице вы найдёте ответы на популярные вопросы о хуках.

В какой версии React появились хуки?

Начиная с релиза 16.8.0, React включает в себя стабильную реализацию хуков для:

Обратите внимание, что хуки будут доступны, только если все React-пакеты версии 16.8.0 или выше. Хуки не будут работать, если вы, например, забыли обновить React DOM.

React Native 0.59 и выше поддерживает хуки.

Надо ли переписать все мои классовые компоненты?

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

Что можно сделать с помощью хуков, чего невозможно добиться, используя классы?

Хуки дают новый мощный способ повторного использования кода в компонентах. «Создание пользовательских хуков» даёт представление об их возможностях. Эта статья, написанная одним из участников команды React, описывает новые возможности, которые открывают хуки.

Какая часть моих знаний о React всё ещё актуальна?

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

Однако, хуки — не самая простая часть React. Если вам чего-то не хватает в этой документации, дайте нам знать, и мы постараемся вам помочь.

Что мне использовать: хуки, классы или оба подхода?

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

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

Дают ли хуки все возможности классов?

Хуки появились совсем недавно, и некоторые сторонние библиотеки могут быть ещё не совместимы с ними.

Являются ли хуки заменой рендер-пропсам и компонентам высшего порядка?

Как правило, рендер-пропсы и компоненты высшего порядка рендерят только один дочерний компонент, увеличивая вложенность в дереве, но добавляя потомку новую функциональность. Мы думаем, что хуки — более простой способ сделать это. Оба подхода всё ещё имеют право на жизнь (например, компонент, следящий за скроллом, может иметь проп renderItem или компонент-контейнер может иметь разные рендер-пропсы для различных слотов). Но в большинстве случаев хуки должны помочь уменьшить вложенность компонентов в вашем дереве.

Как хуки повлияют на популярные API, такие как Redux connect() и React Router?

Вы можете продолжить использовать тот же самый API, который вы использовали — всё продолжит работать как прежде.

Начиная с версии 5.1 появилась поддержка хуков в React Router.

В будущем другие библиотеки могут также начать поддерживать хуки.

Поддерживают ли хуки статическую типизацию?

Хуки спроектированы с учётом статической типизации. Так как они являются функциями, их легче правильно типизировать чем, например, компоненты высшего порядка. Последние версии определений типов React для Flow и TypeScript поддерживают хуки.

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

Как тестировать компоненты, которые используют хуки?

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

Рецепты Тестирования включают в себя множество примеров, которые вы можете скопировать себе.

Например, у нас есть следующий компонент-счётчик:

Мы будем тестировать этот компонент с помощью React DOM. Чтобы убедиться, что поведение совпадает с тем, что случится в браузере, мы обернём код рендера и обновления в вызов ReactTestUtils.act() :

Вызовы act() также запустят эффекты внутри.

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

Для уменьшения однотипного кода, мы советуем использовать библиотеку React Testing Library. Она была создана для написания тестов, использующих ваши компоненты и имитирующих поведение пользователей в браузере.

За более подробной информацией обратитесь к Рецептам Тестирования.

Что конкретно проверяют правила линтера в хуках?

Мы предоставляем плагин к ESLint, который принуждает следовать правилам хуков, чтобы избежать ошибок. Подразумевается, что любая функция, имя который начинается с « use » и заглавной буквы далее, является хуком. Мы понимаем, что это предположение не идеальное, и могут случаться ложные срабатывания. Однако, без этого важного соглашения, было бы невозможно заставить хуки работать хорошо, а более длинные имена могли бы помешать людям начать использовать хуки или следовать соглашению.

Правила линтера проверяют, что:

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

От классов к хукам

Как методы жизненного цикла соответствуют хукам?

Как осуществлять запросы за данными с помощью хуков?

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

Есть ли что-то вроде переменных экземпляра?

Да! Хук useRef() может использоваться не только для DOM-рефов. Реф — это общий контейнер, а его свойство current — изменяемое и может хранить любое значение, подобно свойству экземпляра класса.

Вы можете использовать его внутри useEffect :

Для объявления интервала нам не понадобится реф ( id может быть локальным относительно эффекта). Но это будет полезно, если потребуется сбросить интервал из обработчика события:

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

Сколько переменных состояния я могу использовать — одну или несколько?

Если вы привыкли писать классовые компоненты, вы скорее всего захотите вызывать useState() однократно и сразу сохранить всё состояние в одном объекте. Да, вы можете так сделать. Взгляните на пример компонента, который следует за движением курсора. Мы храним позицию и размер этого компонента в локальном состоянии.

В разделении состояния на независимые переменные есть ещё одно преимущество. Это поможет легко вынести некоторую логику в отдельный хук в будущем, например:

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

Могу ли я использовать эффект только на обновлениях компонента?

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

Как получить предыдущие пропсы или состояние?

Сейчас, вы можете сделать это вручную, используя реф:

Это может показаться усложнённым, но вы можете вынести эту логику в отдельный хук:

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

Почему я вижу устаревшие пропсы или состояние в моей функции?

Если вы сперва кликнете по «Показать предупреждение», а потом увеличите счётчик, то предупреждение отобразит значение переменной count на момент нажатия по кнопке «Показать предупреждение». Такое поведение предотвращает баги в коде, который предполагает, что пропсы и состояние не меняются.

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

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

В этом примере, мы храним предыдущее значение пропа row в состоянии, что позволяет сравнить значения:

Существует что-нибудь наподобие forceUpdate?

Оба хука useState и useReducer игнорируют обновления, если следующее значение равно предыдущему. Мутация состояния и вызов setState не приведут к повторному рендеру.

Обычно, вы не должны мутировать внутреннее состояние в React. Однако, в качестве лазейки, вы можете использовать увеличивающийся счётчик, чтобы заставить компонент повторно рендериться, если состояние не изменилось:

Старайтесь избегать этого подхода, если возможно.

Могу ли я изменить реф, переданный в функциональный компонент?

Как я могу измерить узел DOM?

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

Мы не выбрали useRef в этом примере, потому что объект рефа не уведомляет нас об изменениях текущего значения рефа. Использование колбэк-рефа гарантирует, что даже если дочерний компонент отображает измеренный узел позже (например, в ответ на клик), мы по-прежнему получаем уведомление об этом в родительском компоненте и можем обновлять измерения.

В данном примере колбэк-реф будет вызван только при монтировании и размонтировании компонента, хотя отрендеренный компонент

остаётся на месте при последующих повторных рендерах. Если необходимо отследить изменение размера компонента, воспользуйтесь ResizeObserver или сторонним хуком, использующий этот API.

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

Если вы не знакомы с этим синтаксисом, ознакомьтесь с объяснением в документации хука состояния.

Могу ли я пропустить эффект при обновлениях?

Да. Ознакомьтесь с условным вызовом эффектов. Обратите внимание, что забыв обработать обновления, вы зачастую можете создать ошибки. Поэтому это и не является поведением по умолчанию.

Безопасно ли не указывать функции в списке зависимостей?

Вообще говоря, это небезопасно.

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

Если после такого изменения мы видим, что никакие значения из области видимости компонента не используются, то можно безопасно указать [] :

В зависимости от ситуации, может пригодиться один из вариантов, описанных ниже.

Давайте разберёмся, почему это важно.

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

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

Это также позволяет обрабатывать ответы, пришедшие не в порядке запросов, с помощью локальной переменной внутри эффекта:

Мы переместили функцию внутрь эффекта, так что её не нужно указывать в списке зависимостей.

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

Если по какой-то причине вы не можете переместить функцию в эффект, есть другие варианты:

Что делать, если зависимости эффекта изменяются слишком часто?

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

(Идентичность функции setCount гарантирована, поэтому её можно безопасно не включать в список зависимостей.)

Теперь обратный вызов setInterval выполняется один раз в секунду, но каждый раз, когда внутренний вызов setCount может использовать обновленное значение для count (называемое c в обратном вызове здесь.)

В крайнем случае если вы хотите реализовать что-то наподобие this в классах, вы можете использовать реф, чтобы хранить в нём изменяемую переменную. Тогда можно писать и читать из него. Например:

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

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

Как закешировать вычисления?

Хук useMemo позволяет вам закешировать вычисления между несколькими рендерами, путём запоминания прошлого результата:

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

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

Как лениво создавать большие объекты?

Хук useMemo позволяет вам закешировать ресурсозатратные вычисления, если зависимости не изменились. Однако, этот способ не гарантирует, что повторных вычислений не случится. Иногда вам нужно удостовериться, что объект будет создан только один раз.

Первый частый вариант использования — создание изначального состояния затратно:

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

Этот подход позволяет избежать создания больших объектов на всех этапах, кроме первого рендера, когда это действительно необходимо. Если вы используете Flow или TypeScript, вы можете также установить для getObserver() непустой тип для уверенности.

Являются ли хуки медленными из-за создания функций на каждом рендере?

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

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

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

Хук useCallback позволяет сохранять ту же самую ссылку на колбэк между повторными рендерами, поэтому shouldComponentUpdate продолжит корректную работу:

Как избежать передачи колбэков вниз?

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

В качестве альтернативы для больших деревьев компонентов мы рекомендуем передавать вниз функцию dispatch из хука useReducer через контекст:

Этот вариант более удобен как с точки зрения поддержки кода (не нужно добавлять пропсы для новых колбэков), так и в разрезе избежания общих проблем с колбэками. Передача функции dispatch по такому принципу — это рекомендуемый подход для вызова колбэков и избежания нежелательных обновлений в глубине дерева компонентов.

Обратите внимание, что вы также можете передавать состояние приложения вниз через пропсы (более явно) или через контекст (более удобно для глубокого дерева). Если ваш контекст в том числе передаёт некое состояние, используйте два разных типа контекста. Так как контекст dispatch никогда не изменяется, то компоненты, использующие его, не будут нуждаться в повторном рендере, если только им не требуется ещё и контекст с состоянием приложения.

Мы рекомендуем передавать dispatch вниз через контекст вместо передачи отдельных колбэков через пропсы. Следующий подход приведён тут только для полноты картины в качестве лазейки.

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

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

Как React связывает вызовы хуков с компонентом?

React следит за тем, какой компонент рендерится в данный момент. Благодаря правилам хуков, мы знаем, что хуки вызываются только из React-компонентов (пользовательские хуки также вызываются только из React-компонентов).

Что послужило прообразом хуков?

Хуки были основаны на следующих идеях и экспериментах:

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *