Useref react что это
Useref react что это
Хук useRef позволяет сохранить некоторый объект, который можно можно изменять и который хранится в течение всей жизни компонента.
Расспространенным примером применения useRef является хранение ссылки на html-элементы внутри компонента:
Здесь в компоненте сначала создается ссылка ref:
Однако только операциями с элементами html применение useRef не ограничивается. В реальности useRef может хранить любой объект, и это может быть полезно в различных ситуациях.
Например, рассмотрим ситуацию, когда вначале компонент загружает состояние из LocalStorage, а после окончания работы с компонентом при завершении его жизненного цикла он сохраняет состояние обратно в LocalStorage. На первый взгляд мы можем обойтись одним хуком useEffect :
Вначале в компоненте определяет начальное состояние в виде переменной name:
Далее в хуке React.useEffect() загружаем данные из LocalStorage:
И чтобы сохранять данные, оператору return передается функция сохранения данных:
Для имитации удаления компонента и завершения его жизненного цикла в нем предумотрена кнопка, по нажатию на которую мы ожидаем, что произойдет сохранение значения переменной name в localStorage. Однако поведение программы будет несколько иное:
Поскольку useEffect срабатывает в данном случае один раз, то соответственно он берет значение перемеенной name только один раз и никак не отслеживает ее изменения. Мы, конечно, могли бы передать в качестве параметра эту переменную name:
Но тогда бы useEffect вызывался при каждом изменении переменной name.
Теперь применим хук useRef:
Здесь вместе с состоянием компонента определяем ссылку nameRef:
При этом данный эффект зависит от name, то есть срабатывает при любых изменениях значения name.
В отличие от переменной состояния name в useEffect, значение по ссылке nameRef будет изменяться, несмотря на то что, useEffect по-прежнему сработает только один раз
Hooks API Reference
Hooks are a new addition in React 16.8. They let you use state and other React features without writing a class.
This page describes the APIs for the built-in Hooks in React.
If you’re new to Hooks, you might want to check out the overview first. You may also find useful information in the frequently asked questions section.
Returns a stateful value, and a function to update it.
During the initial render, the returned state ( state ) is the same as the value passed as the first argument ( initialState ).
The setState function is used to update the state. It accepts a new state value and enqueues a re-render of the component.
During subsequent re-renders, the first value returned by useState will always be the most recent state after applying updates.
React guarantees that setState function identity is stable and won’t change on re-renders. This is why it’s safe to omit from the useEffect or useCallback dependency list.
The ”+” and ”-” buttons use the functional form, because the updated value is based on the previous value. But the “Reset” button uses the normal form, because it always sets the count back to the initial value.
If your update function returns the exact same value as the current state, the subsequent rerender will be skipped completely.
Unlike the setState method found in class components, useState does not automatically merge update objects. You can replicate this behavior by combining the function updater form with object spread syntax:
Lazy initial state
The initialState argument is the state used during the initial render. In subsequent renders, it is disregarded. If the initial state is the result of an expensive computation, you may provide a function instead, which will be executed only on the initial render:
Bailing out of a state update
If you update a State Hook to the same value as the current state, React will bail out without rendering the children or firing effects. (React uses the Object.is comparison algorithm.)
Accepts a function that contains imperative, possibly effectful code.
Mutations, subscriptions, timers, logging, and other side effects are not allowed inside the main body of a function component (referred to as React’s render phase). Doing so will lead to confusing bugs and inconsistencies in the UI.
By default, effects run after every completed render, but you can choose to fire them only when certain values have changed.
Cleaning up an effect
Often, effects create resources that need to be cleaned up before the component leaves the screen, such as a subscription or timer ID. To do this, the function passed to useEffect may return a clean-up function. For example, to create a subscription:
The clean-up function runs before the component is removed from the UI to prevent memory leaks. Additionally, if a component renders multiple times (as they typically do), the previous effect is cleaned up before executing the next effect. In our example, this means a new subscription is created on every update. To avoid firing an effect on every update, refer to the next section.
Although useEffect is deferred until after the browser has painted, it’s guaranteed to fire before any new renders. React will always flush a previous render’s effects before starting a new update.
Conditionally firing an effect
The default behavior for effects is to fire the effect after every completed render. That way an effect is always recreated if one of its dependencies changes.
However, this may be overkill in some cases, like the subscription example from the previous section. We don’t need to create a new subscription on every update, only if the source prop has changed.
To implement this, pass a second argument to useEffect that is the array of values that the effect depends on. Our updated example now looks like this:
Now the subscription will only be recreated when props.source changes.
If you use this optimization, make sure the array includes all values from the component scope (such as props and state) that change over time and that are used by the effect. Otherwise, your code will reference stale values from previous renders. Learn more about how to deal with functions and what to do when the array values change too often.
If you want to run an effect and clean it up only once (on mount and unmount), you can pass an empty array ( [] ) as a second argument. This tells React that your effect doesn’t depend on any values from props or state, so it never needs to re-run. This isn’t handled as a special case — it follows directly from how the dependencies array always works.
If you pass an empty array ( [] ), the props and state inside the effect will always have their initial values. While passing [] as the second argument is closer to the familiar componentDidMount and componentWillUnmount mental model, there are usually better solutions to avoid re-running effects too often. Also, don’t forget that React defers running useEffect until after the browser has painted, so doing extra work is less of a problem.
We recommend using the exhaustive-deps rule as part of our eslint-plugin-react-hooks package. It warns when dependencies are specified incorrectly and suggests a fix.
The array of dependencies is not passed as arguments to the effect function. Conceptually, though, that’s what they represent: every value referenced inside the effect function should also appear in the dependencies array. In the future, a sufficiently advanced compiler could create this array automatically.
Accepts a context object (the value returned from React.createContext ) and returns the current context value for that context. The current context value is determined by the value prop of the nearest above the calling component in the tree.
Don’t forget that the argument to useContext must be the context object itself:
A component calling useContext will always re-render when the context value changes. If re-rendering the component is expensive, you can optimize it by using memoization.
useContext(MyContext) only lets you read the context and subscribe to its changes. You still need a above in the tree to provide the value for this context.
Putting it together with Context.Provider
This example is modified for hooks from a previous example in the Context Advanced Guide, where you can find more information about when and how to use Context.
The following Hooks are either variants of the basic ones from the previous section, or only needed for specific edge cases. Don’t stress about learning them up front.
useReducer is usually preferable to useState when you have complex state logic that involves multiple sub-values or when the next state depends on the previous one. useReducer also lets you optimize performance for components that trigger deep updates because you can pass dispatch down instead of callbacks.
Here’s the counter example from the useState section, rewritten to use a reducer:
React guarantees that dispatch function identity is stable and won’t change on re-renders. This is why it’s safe to omit from the useEffect or useCallback dependency list.
Specifying the initial state
There are two different ways to initialize useReducer state. You may choose either one depending on the use case. The simplest way is to pass the initial state as a second argument:
React doesn’t use the state = initialState argument convention popularized by Redux. The initial value sometimes needs to depend on props and so is specified from the Hook call instead. If you feel strongly about this, you can call useReducer(reducer, undefined, reducer) to emulate the Redux behavior, but it’s not encouraged.
It lets you extract the logic for calculating the initial state outside the reducer. This is also handy for resetting the state later in response to an action:
Bailing out of a dispatch
If you return the same value from a Reducer Hook as the current state, React will bail out without rendering the children or firing effects. (React uses the Object.is comparison algorithm.)
Returns a memoized callback.
Pass an inline callback and an array of dependencies. useCallback will return a memoized version of the callback that only changes if one of the dependencies has changed. This is useful when passing callbacks to optimized child components that rely on reference equality to prevent unnecessary renders (e.g. shouldComponentUpdate ).
The array of dependencies is not passed as arguments to the callback. Conceptually, though, that’s what they represent: every value referenced inside the callback should also appear in the dependencies array. In the future, a sufficiently advanced compiler could create this array automatically.
We recommend using the exhaustive-deps rule as part of our eslint-plugin-react-hooks package. It warns when dependencies are specified incorrectly and suggests a fix.
Pass a “create” function and an array of dependencies. useMemo will only recompute the memoized value when one of the dependencies has changed. This optimization helps to avoid expensive calculations on every render.
If no array is provided, a new value will be computed on every render.
You may rely on useMemo as a performance optimization, not as a semantic guarantee. In the future, React may choose to “forget” some previously memoized values and recalculate them on next render, e.g. to free memory for offscreen components. Write your code so that it still works without useMemo — and then add it to optimize performance.
The array of dependencies is not passed as arguments to the function. Conceptually, though, that’s what they represent: every value referenced inside the function should also appear in the dependencies array. In the future, a sufficiently advanced compiler could create this array automatically.
We recommend using the exhaustive-deps rule as part of our eslint-plugin-react-hooks package. It warns when dependencies are specified incorrectly and suggests a fix.
A common use case is to access a child imperatively:
You might be familiar with refs primarily as a way to access the DOM. If you pass a ref object to React with
However, useRef() is useful for more than the ref attribute. It’s handy for keeping any mutable value around similar to how you’d use instance fields in classes.
Prefer the standard useEffect when possible to avoid blocking visual updates.
useDebugValue can be used to display a label for custom hooks in React DevTools.
For example, consider the useFriendStatus custom Hook described in “Building Your Own Hooks”:
We don’t recommend adding debug values to every custom Hook. It’s most valuable for custom Hooks that are part of shared libraries.
Defer formatting debug values
In some cases formatting a value for display might be an expensive operation. It’s also unnecessary unless a Hook is actually inspected.
For this reason useDebugValue accepts a formatting function as an optional second parameter. This function is only called if the Hooks are inspected. It receives the debug value as a parameter and should return a formatted display value.
For example a custom Hook that returned a Date value could avoid calling the toDateString function unnecessarily by passing the following formatter:
createRef, setRef, useRef и зачем нужен current в ref
Вспоминаем setRef
Почему такой подход мне нравится, в нем почти отсутствует магия. Вы контролируете почти весь код, разве что кроме момента передачи функции в атрибут ref и кто-то ее там вызывает, но и это выглядит вполне себе привычно, когда мы хотим получить значение после асинхронной операции с помощью callback.
Вопросы к createRef
Далее мы этот объект < current: null >засовываем в атрибут ref и уже в componentDidMount имеем доступ к ноде.
Тут у меня возникает сразу несколько вопросов:
Изучаем исходники createRef
Чтобы во всем этом разобраться, я предлагаю изучить исходники реакта. Начнем с метода createRef() (ссылка).
Изучаем исходники работы атрибута ref
Изучив этот код становится понятно, что полный сценарий работы с ref достаточно примитивный
Исходя из этих знаний, мы можем предположить, что скорей всего проверка на существование свойства current избыточна. Чтобы уже точно подтвердить это, я полез в типы:
И действительно поле current не имеет вопросительного знака, а это значит оно обязательное. Поэтому можете смело использовать поле current без дополнительных проверок.
А что происходит в commitAttachRef при 2-ом рендере?
Код который мы изучили, описывает только первый рендер, давайте разберемся что происходит с ref на второй и последующие рендеры.
Для этого было решено провести еще один эксперимент. В начале метода commitAttachRef я добавил console.log
В браузере же мы увидим следующую картину:
Давайте еще доработаем пример и попробуем вставить значение счетчика в className этого div-а
И поведение в браузере не изменилось от такой доработки. commitAttachRef по прежнему вызывается лишь 1 раз.
А что если использовать createRef вместо useRef?
В предыдущих экспериментах мы разбирали примеры использования createRef() на классах, а что будет если createRef() использовать в функциональных компонентах?
Поэтому я решил переписать предыдущий пример на хуках. Получилась следующая картина:
Изучаем исходники useRef
Сравниваем поведение при createRef и useRef
Для того чтобы показать, что создается именно новый объект, я решил ввести обозначение буквами. Если после какого-то действия буква возле объекта остаётся прежней, значит это та же ссылка на объект. Если же буква изменится, значит это полностью новый объект.
А теперь, построим временную сравнительную шкалу для сравнения useRef() и createRef()
Для разгадки этой тайны, проведем 2 мелких эксперимента:
Эксперимент 1. Сохраняем ту же ссылку на объект и обнуляем current
Рассмотрим следующий код:
РЕЗУЛЬТАТ: commitAttachRef вызывается лишь 1 раз, при маунте компонент
Эксперимент 2. Изменяем ссылку на объект и сохраняем current
Рассмотрим следующий код:
РЕЗУЛЬТАТ: commitAttachRef вызывается на каждый рендер
Паттерн единого объекта с мутирующим свойством
Мысли вслух
Введение в React Hooks
Мотивация стоящая за Hooks
Хотя компоненто-ориентированная архитектура позволяет нам повторно использовать view в нашем приложении, одна из самых больших проблем, с которыми сталкивается разработчик, заключается в том, как повторно использовать логику, находящуюся в state, между компонентами. Когда у нас есть компоненты, которые имеют сходную логику состояния, нет хороших решений для переиспользования компонентов, и это иногда может привести к дублированию логики в конструкторе и методах жизненного цикла.
Чтобы решить эту проблему, обычно используют:
Hooks нацелены на решение всех этих проблем, позволяя вам писать функциональные компоненты, которые имеют доступ к state, context, методам жизненного цикла, ref и т. д., без написания классов.
Hooks в Alpha
Прежде чем мы погрузимся, важно упомянуть, что разработка Hooks API еще не завершена.
Кроме того, официальная документация очень хороша, и мы рекомендуем ее прочитать еще и потому, что в ней расширенно описана мотивация, стоящая за введением Hooks.
UPD Оригинальная статья, перевод которой вы читаете была написана еще в то время, когда это API было в alpha тестировании, на данный момент React Hooks официально готовы к использованию. Необратимые изменения, привнесенные в релиз (по сравнению с альфой) можно посмотреть внизу статьи или в релизных заметках.
Как Hooks соотносятся с классами
Напомним, что при написании классов компонентов нам часто необходимо:
С помощью React Hooks мы можем воспроизвести аналогичное поведение в функциональных компонентах:
Для использования Hooks необходима последняя версия React
Вы можете начать работу с Hooks прямо сейчас, сменив значение react и react-dom в вашем package.json на «next».
Пример useState() Hook
State является неотъемлемой частью React. Он позволяет нам объявлять переменные, которые содержат данные, которые, в свою очередь, будут использоваться в нашем приложении. С помощью классов state обычно определяется следующим образом:
В вышеприведенном блоке кода, мы начинаем с импорта useState из React. UseState — это новый способ использования возможностей, которые раньше могло предложить this.state.
Затем обратите внимание, что этот компонент является функцией, а не классом. Интересно!
Чтение и запись state
Внутри этой функции мы вызываем useState для создания переменной в state:
useState используется для объявления переменной state и может быть инициализирован любым типом значения (в отличие от state в классах, который должен быть объектом).
Затем мы применяем их как обработчики событий на кнопках во view:
React отслеживает state
Когда нажимается кнопка «On», Вызывается функция setOn, вызывающая setLight(1). Вызов setLight(1) обновляет значение light для следующего рендера. Это может показаться немного волшебным, но React отслеживает значение этой переменной и будет передавать новое значение, когда происходит ре-рендер этого компонента.
Затем мы используем текущее состояние (light), чтобы определить, должна ли лампа быть включена или нет. То есть, мы устанавливаем цвет заливки SVG в зависимости от значения light. Если light равен 0 (выкл.), То для fillColor установлено значение # 000000 (а если равен 1 (включено), fillColor устанавливается на # ffbb73).
Multiple States
Хотя мы не делаем этого в приведенном выше примере, вы можете создать несколько state, вызвав useState более одного раза. Например:
ПРИМЕЧАНИЕ.
Существуют некоторые ограничения при использовании hooks, о которых вы должны знать. Самое главное, вы должны вызывать hooks только на верхнем уровне вашей функции. См. «Правила hooks» для получения дополнительной информации.
Пример useEffect() Hook
Используя useEffect() Hook, React знает, что вы хотите выполнить определенное действие после рендеринга.
Давайте посмотрим на пример ниже. Мы будем использовать useEffect() для вызова API и получения ответа.
В этом примере кода используются как useState, так и useEffect, и это потому, что мы хотим записать результат вызова API в state.
Получение данных и обновления state
Чтобы «использовать эффект», нам нужно поместить наш action в функцию useEffect, то есть мы передаем «action» эффект как анонимную функцию, как первый аргумент useEffect.
В примере выше мы обращаемся к API, которое возвращает список имен. Когда возвращается response, мы конвертируем его в JSON, а затем используем setNames(data) для установки state.
Проблемы с производительностью при использовании Effects
Однако стоит сказать еще кое-что об использовании useEffect.
Первое, о чем нужно подумать, это то, что по умолчанию наш useEffect будет вызываться на каждом рендере! Хорошей новостью является то, что нам не нужно беспокоиться об устаревших данных, но плохая новость заключается в том, что мы, вероятно, не хотим делать HTTP-запрос для каждого рендеринга (как в этом случае).
В приведенном выше примере кода обратите внимание, что мы передаем пустой массив в качестве второго аргумента. Это мы говорим React, что мы хотим только назвать этот effect при монтировании компонента.
Кроме того, как и функция useState, useEffect позволяет использовать несколько экземпляров, что означает, что вы можете иметь несколько функций useEffect.
Пример useContext() Hook
Контекст в React- это способ для дочернего компонента получить доступ к значению в родительском компоненте.
Чтобы понять необходимость context: при создании React приложения вам часто нужно передавать значения с верха вашего дерева React вниз. Не используя context, вы передаете props через компоненты, которым не обязательно о них знать.
Передача props вниз по дереву «несвязанных» компонентов ласково называется props drilling.
React Context решает проблему props drilling, позволяя вам делиться значениями через дерево компонентов, с любым компонентом, который запрашивает эти значения.
useContext() упрощает использование context
С useContext Hook использование context стает проще, чем когда-либо.
Функция useContext() принимает объект сontext, который изначально возвращается из React.createContext(), а затем возвращает текущее значение контекста. Давайте посмотрим на пример ниже.
В приведенном выше коде context JediContext создается с использованием React.createContext().
Мы используем JediContext.Provider в нашем App компоненте и устанавливаем там значение «Luke». Это означает, что любой компонент, которому нужно получить доступ к context теперь сможет считать это значение.
Чтобы прочитать это значение в функции Display(), мы вызываем useContext, передавая аргумент JediContext.
Затем мы передаем объект context, который мы получили из React.createContext, и он автоматически выводит значение. Когда значение провайдера будет обновляться, этот Hook автоматически сработает с последним значением context.
Получение ссылки на context в более крупном приложении
Выше мы создали JediContext в рамках обоих компонентов, но в более крупном приложении Display и App будут находиться в разных файлах. Поэтому, если у вас похожая ситуация, вам может быть интересно: «Как мы получаем ссылку на JediContext между файлами?»
Ответ заключается в том, что вам нужно создать новый файл, который экспортирует JediContext.
Например, у вас может быть файл context.js, который содержит что-то вроде этого:
и потом в App.js (и Display.js) вы должны написать:
Пример useRef() Hook
useRef() и формы с input
Давайте посмотрим пример использования useRef() hook.
В приведенном выше примере мы используем useRef() в сочетании с useState(), чтобы отрендерить значение input в тег p.
Ref создается в переменной nameRef. Затем переменную nameRef можно использовать в input, задав как ref. По существу, это означает, что теперь содержимое поля ввода будет доступно через ref.
Кнопка отправки в коде имеет обработчик события onClick, называемый submitButton. Функция submitButton вызывает setName (созданный через useState).
Как мы уже делали с использованием hookState, setName будет использоваться для установки state name. Чтобы извлечь имя из тега input, мы читаем значение nameRef.current.value.
Еще одно замечание относительно useRef заключается в том, что его можно использовать больше, чем атрибут ref.
Использование пользовательских Hooks
Одной из самых крутых особенностей Hooks является то, что вы можете легко делиться логикой между несколькими компонентами, создавая собственный Hook.
В приведенном ниже примере мы создадим пользовательский setCounter() Hook, который позволяет нам отслеживать состояние и предоставлять настраиваемые функции обновления state!
В приведенном выше блоке кода мы создаем функцию useCounter, которая хранит логику нашего hook.
Обратите внимание, что useCounter может использовать другие Hooks! Начнем с создания нового состояния Hook через useState.
Затем мы определяем две вспомогательные функции: increment и decrement, которые вызывают setCount и соответственно корректируют текущий count.
Наконец, мы возвращаем ссылки, необходимые для взаимодействия с нашим Hook.
В: Что происходит, возврат массива с объектом?
О: Ну, как и большинство вещей в Hooks, соглашения API еще не завершены. Но то, что мы делаем здесь, возвращает массив, где:
Тем не менее, вы можете вернуть все, что захотите, из своего кастомного Hook.
В приведенном выше примере мы используем increment и decrement как обработчики onClick, в нашем view. Когда пользователь нажимает кнопки, счетчик обновляется и повторно отображается (как myCount) во view.
Написание тестов для React Hooks
Чтобы написать тесты для hooks, мы будем использовать библиотеку для тестирования react-testing-library.
С тестированием hooks еще не все понятно. В настоящее время вы не можете протестировать hook изолированно. Вместо этого вам нужно прикрепить свой hook к компоненту и протестировать этот компонент.
Итак, ниже мы будем писать тесты для наших Hooks, взаимодействуя с нашими компонентами, а не с Hooks напрямую. Хорошая новость заключается в том, что наши тесты будут выглядеть как обычные тесты React.
Тестирование useState() Hook
Давайте посмотрим пример написания тестов для useState Hook. В приведенном выше уроке мы тестируем больше вариаций используемого выше примера useState. Мы будем писать тесты, чтобы убедиться, что нажатие кнопки «Off» Устанавливает состояние в 0 и нажатие кнопки «On» Устанавливает состояние в 1.
В вышеприведенном блоке кода мы начинаем с импорта некоторых хелперов из react-testing-library и тестируемого компонента.
Тест проверяет, что, если нажимается onButton, значение state устанавливается в 1, а при нажатии на offButton state равен 1.
Тестирование useEffect() Hook
В этом примере мы будем писать тесты, чтобы добавить товар в корзину, используя useEffect Hook. Количество элементов также сохраняется в localStorage. Файл index.js в CodeSandbox ниже содержит фактическую логику, используемую для добавления элементов в корзину.
Мы будем писать тесты, чтобы убедиться, что обновление количества элементов корзины также отражено в localStorage, и даже если страница перезагрузилась, количество элементов корзины все еще остается прежним.
В функции, подтверждающей прохождение теста мы сначала устанавливаем cartItem в localStorage равным 0, что означает, что количество элементов корзины равно 0. Затем мы получаем как container так и rerender из компонента App через деструктурирование. Rerender позволяет нам имитировать перезагрузку страницы.
Затем мы получаем ссылки на кнопки и тег p, который отображает текущее значение корзины и устанавливает их в переменные.
Как только это будет сделано, тест затем имитирует щелчок на addButton и проверяет, является ли текущий счетчик корзины равным 1 и перезагружает страницу, после чего, если он проверяет, установлено ли значение localStorage, cartItem, равным 1. Затем он моделирует нажатие на resetButton и проверяет, установлено ли текущее количество элементов корзины равным 0.
Тестирование useRef () Hook
В этом примере мы будем тестировать useRef Hook, и мы будем использовать исходный пример useRef, приведенный выше в качестве основы для теста. UseRef используется для получения значения из поля ввода, а затем устанавливает значение state. Файл index.js в CodeSandbox ниже содержит логику ввода значения и его отправки.
В функции, утверждающей прохождение теста мы устанавливаем переменные в поле input, тег p, который отображает текущее значение ref, и кнопку отправки. Мы также устанавливаем значение, которое мы хотели бы ввести в поле ввода, для переменной newName. Это будет использоваться для проверки в тесте.
Метод fireEvent.change используется для ввода значения в поле input, и в этом случае используется name, сохраненное в константе newName, после чего нажимается кнопка отправки.
Затем тест проверяет, соответствует ли значение ref после нажатия кнопки значение newName.
Наконец, вы должны увидеть «Нет падений тестов, поздравляем!» сообщение в консоли.
Реакция сообщества на Hooks
С того момента как представили React Hooks, сообщество было в восторге от этой фичи, и мы видели множество примеров и примеров использования React Hooks. Вот некоторые из основных:
Различные типы hooks
Существуют различные типы hooks, которые вы можете начать использовать в своем React приложении. Они перечислены ниже:
Будущее hooks
Тем не менее, Hooks все еще являются экспериментальной функцией, и команда React неоднократно предупреждала, что API может быть изменен. Считайте что вы предупреждены.
Что означает для классов появление Hooks? Как сообщает команда React, классы все еще остаются, они являются огромной частью кодовой базы React и, скорее всего, будут еще какое-то время.
У нас нет планов осуждать классы. В Facebook у нас есть десятки тысяч компонентов, написанных классами, и, как и вы понимаете, мы не собираемся переписывать их. Но если сообщество React одобрит Hooks, нет смысла иметь два разных рекомендуемых способа записи компонентов — Дэн Абрамов
Хотя конкретный API-интерфейс Hooks является экспериментальным сегодня, сообщество одобряет идею Hooks, поэтому я думаю, что они останутся с нами надолго.