📖Предисловие
Эта статья представляет собой учебную заметку, записанную мной во время изучения ReactHooks, Содержание не ограничивается содержанием документа, но также связано с исходным кодом Hooks. Если есть ошибки, пожалуйста, исправьте их вовремя.
❓ Что такое крючок Зачем нужен крючок?
Рекомендуется заглянуть в блог Дэна Абрамова
- Логическое повторное использование, если вы используете такие функции, как компоненты более высокого порядка, является более сложным.
- Традиционные функциональные компоненты не могут хранить состояние.
- Хуки позволяют вызывать функции React в функциональных компонентах.
- Использование пользовательских хуков может упростить повторное использование логики.
- Хуки — это будущее React
- Крючки — это не волшебство. Хуки также спроектированы так, чтобы не зависеть от React.
⛰️useState
useState может добавить хук состояния в функциональный компонент.
Вызов useState возвращает переменную состояния, а также метод для обновления переменной состояния. Параметр useState является начальным значением переменной состояния,Начальное значение действительно только при первом рендеринге..
Метод обновления переменной состояния не объединяет состояние, как это делает this.setState. Вместо этого замените переменную состояния.
Ниже приведен простой пример, который отображает значение count на странице и нажимает кнопку setCount, чтобы обновить значение count.
функциональное обновление
Если новое состояние необходимо вычислить из предыдущего состояния. Вы можете передать функцию функции обновления, возвращаемой useState. Аргументом функции является предыдущее состояние.
ленивый инициализатор
Начальное значение useState ленивое и работает только при первом рендеринге компонента. Если начальное значение состояния необходимо получить с помощью сложных вычислений, начальное значение useState также может быть функцией, а возвращаемое значение функции будет начальным значением useState.
пропустить обновление состояния
При вызове функции обновления состояния передается то же состояние, что и текущее состояние. React пропускает рендеринг дочерних компонентов и выполнение эффектов.
подраздел
- Обновления useState являются заменами, а не слияниями.
- useState может получать параметры функции и использовать возвращаемое значение функции в качестве начального значения.
- Функция обновления useState может получать в качестве параметра функцию, а параметром функции является значение состояния предыдущего состояния.
- При использовании текущего значения обновления состояния не будут запускать рендеринг.
- Несколько useStates могут использоваться для объявления нескольких переменных состояния.
🏁использоватьЭффект
В дополнение к официальной документации рекомендуется прочитатьUm guia completo para useEffect
useEffect позволяет нам выполнять побочные эффекты в функциональных компонентах. Привязка событий, запрос данных, динамическая модификация DOM.
useEffect будет вВыполнить каждую рендеринг RACT. То ли это первое крепление, то ли обновление. (Конечно, мы можем контролировать это поведение)
Эффекты, которые необходимо очистить
В традиционных компонентах класса прослушиватели событий обычно добавляются в componentDidMount. Прослушиватель события очищается в componentWillUnmount. Нам нужно разделить нашу логику на разные функции жизненного цикла.
И эффект может вернуть функцию, и когда реакция будет очищена, возвращенная функция будет выполнена. Всякий раз, когда этот эффект выполняется, предыдущий эффект сбрасывается. Очистка также выполняется при удалении компонента.
То есть в коде ниже. Каждое обновление удаляет предыдущий эффект и выполняет текущий эффект.
эффект оптимизации производительности
Каждый раз при выполнении эффекта очистка предыдущего эффекта может привести к ненужной потере производительности. Мы можем управлять выполнением эффекта через второй параметр эффекта. Второй параметр — это зависимость useEffect, useEffect будет обновляться только при изменении зависимости.
Когда мы передаем пустой массив в качестве зависимости, он сообщает React, что эффект не зависит ни от какого состояния или свойств. Мы можем использовать это поведение для моделирования componentDidMount или componentWillUnmount.
⚠️ Пожалуйста, помнитеСуществует разница между эффектом и componentDidMount с использованием пустого массива.
🤔️В чем разница между useEffect(fn, []) и componentDidMount?
Аналогичный вопрос, почему иногда получается старое состояние или опора в эффекте?
useEffect будет захватывать свойства, состояние, но всегда начальное значение.Как показано на рисунке выше, когда мы нажимаем кнопку несколько раз, обратный вызов эффекта через 3 секунды до сих пор печатает начальное значение состояния.
Почему это происходит?
Это из-за механизма закрытия javascript, После вызова функционального компонента состояние внутри функции не очищается механизмом сборки мусора, поскольку оно зависит от обратного вызова внутреннего таймера, а сохраняется в памяти. Поэтому, когда таймер вызывается и выполняется, печатается переменная, хранящаяся в предыдущем закрытии.
Как не получить старый реквизит или состояние?
- использовать useRef
- Проверьте, отсутствуют ли зависимости, в результате чего эффект не обновляется.
🤔️Как правильно запрашивать данные в useEffect?
Прочитать эту статью — хороший выборHow to fetch data with React Hooks?
Как запросить данные?
Как использовать async/await в useEffect?
Асинхронная функция по умолчанию возвращает объект Promise, в то время как в useEffect разрешается только ничего не возвращать или возвращать функцию очистки. В консоли появится следующее предупреждение **Внимание: функция useEffect должна возвращать функцию очистки или ничего. Промисы и useEffect(async() => …) не поддерживаются, но вы можете вызвать асинхронную функцию внутри эффекта.. **
Решение следующее👇
подраздел
- Для разделения логики можно использовать несколько useEffects. В компонент класса мы обычно добавляем привязку событий, данные запроса и другую несвязанную логику в componentDidMount.
- Если вы хотите, чтобы useEffect выполнялся только один раз при загрузке или один раз при выгрузке компонента, вы можете передать пустой массив в useEffect.
- useEffect не поддерживает прямое использование асинхронных функций.
- Если замыкание сформировано в useEffect, оно получит старые реквизиты или состояние. (Это не имеет отношения к хуку, это связано с характеристиками самого функционального компонента)
- Функция, возвращаемая useEffect, функция очистки. Будет вызываться, когда предыдущий эффект очищается.
📰Правила крючка
- Используйте Hook только на верхнем уровне, а не для оценки, используйте Hook в операторах цикла.
- Используйте хуки только в функциях React
🤔️Почему хук сильно зависит от порядка выполнения?
Анализируем исходный код preact, в preact хук хранится в массиве приватного свойства компонента __hooks._list. От указателя currentIndex зависит как чтение, так и сохранение, при изменении порядка выполнения хуков изменится и текущий индекс, а полученные хуки могут быть выполнены некорректно.
⚙️Индивидуальный крючок
- Пользовательский хук должен начинаться с использования
- Пользовательские хуки — это только логическое повторное использование, и состояние в них не будет передано.
- Пользовательский может вызывать другой внутренний крюк крюка.
- Избегайте преждевременного разделения абстрактной логики
Ниже представлен пользовательский крючок 🌰
💡Пользовательский хук для сбора данных
Когда мы запрашиваем данные двоюродного брата через ajax, используется много общей логики. Например, обработка состояния загрузки, обработка сообщений об ошибках и обработка перелистывания страниц. Мы можем абстрагировать эту логику в публичный хук. Различные API, как параметр кастомного хука.
Ниже приведен пример пользовательского хука запроса данных:
как использовать? Выставьте некоторое состояние и setState из пользовательского хука. При изменении страницы данные будут запрашиваться повторно.
🚀Другие API
useContext
Получает объект контекста и возвращает значение текущего контекста. useContext может подписываться на изменения контекста. Однако компонентам верхнего уровня по-прежнему необходимо использовать
useReducer
useReducer получает три параметра: функцию редуктора, начальное значение initialArg, функцию ленивого начального значения init. Функция редьюсера аналогична редюсеру Redux, полученному состоянию и действиям. Вернуть обновленное состояние. Если вы передадите три аргумента, init(initialArg) будет использоваться как начальное значение.
useReducer больше подходит, чем useState, в сложных сценариях.
указать начальное состояние
Второй параметр useReducer может указывать начальное состояние.
ленивая инициализация
Если указан третий параметр useReducer, начальное значение useReducer будет установлено равнымinit(initialArg)
пропустить отправку
Если состояние, возвращаемое ReducerHook, совпадает с текущим состоянием, React пропустит рендеринг дочерних компонентов и выполнение эффектов.
🌰 Примеры
В примере кастомного хука для управления состоянием используется несколько useState, при появлении большого количества состояний useState сильно усложняет логику. Теперь мы можем использовать useReducer для управления несколькими состояниями и передачи диспетчеров дочерним компонентам вместо обратных вызовов.
Ниже приведен пример пользовательского хука, который запрашивает данные из пользовательского хука и преобразует их в метод useReducer.
useCallback
useCallback получает в качестве параметров функцию обратного вызова и массив зависимостей. useCallback вернетсяmemoizedфункция.当依赖项改变的时候,会返回的新的memoizedфункция.
useMemo
useMemo похож на useCallback. useMemo вернетсяmemoizedстоимость. Пересчитывает при изменении зависимостейmemoizedстоимость.
🌟использоватьСсылка
В дополнение к функции получения узлов dom текущее свойство useRef позволяет легко сохранять любое значение переменной. useRef возвращает один и тот же объект ref каждый раз, когда он отображается.
Представьте себе следующее 👇, когда компонент будет перерендерен, мы никогда не сможем очистить таймер, потому что таймер изменился.
Если вы хотите после обновления, вы можете очистить таймер, вы можете использовать таймер, чтобы сохранить текущее свойство useRef
useLayoutEffect
useLayoutEffect похож на useEffect, но разница в следующем:
- useEffect, использование useEffect не будет блокировать перерисовку браузера
- useLayoutEffect, используя useLayoutEffect, заблокирует перерисовку браузера. Если вам нужно вручную изменить Dom, рекомендуется использовать LayoutEffect. Поскольку, если Дом обновлен в useEffect, useEffect не будет блокировать перерисовку, пользователь может увидеть мерцание из-за обновления,
🚗Ссылка
- Освоение React Hooks за 30 минут
- 🌟КРЮЧКИ (предложение)
- 🌟Making Sense of React Hooks
- Интенсивное чтение "Как использовать React Hooks для сборки колеса"
- Подробные хуки React
- 🌟A Complete Guide to useEffect
- 🌟Making setInterval Declarative with React Hooks
- Hooks in react-spring, a tutorial
- Хуки useCallback и useMemo в React на примере