React Hooks были представлены в React 16.8 как способ использования состояния и других функций React в функциональных компонентах. До появления хуков нам приходилось использовать компоненты класса для доступа к методам жизненного цикла и управления состояниями. Мы можем достичь той же функциональности в функциональных компонентах с помощью хуков, сделав код более кратким и понятным.
В мире функционального реагирования хуки произвели революцию в том, как мы пишем многоразовые и эффективные блоки кода.
Что такое крючки?
Хуки — это функции, которые позволяют нам использовать состояние и другие функции React в функциональных компонентах. Они позволяют нам повторно использовать логику с отслеживанием состояния без изменения иерархии компонентов.
Это функции, которые позволяют нам подключаться к функциям React и управлять состоянием и побочными эффектами в функциональных компонентах. Хуки обеспечивают более простой и лаконичный способ написания повторно используемого и тестируемого кода.
React предоставляет несколько встроенных хуков, таких как useState
, useEffect
, useCallback
и useMemo
и другие.
Некоторые из преимуществ, которые хуки предлагают по сравнению с традиционными компонентами класса, включают:
- Простой код. Хуки устраняют необходимость в компонентах класса и обеспечивают более простой подход к управлению состоянием и побочными эффектами.
- Повторное использование кода. Хуки позволяют повторно использовать логику с отслеживанием состояния в нескольких компонентах, уменьшая дублирование кода.
- Улучшенная читабельность. Крючки упрощают понимание и анализ поведения отдельных компонентов.
- Тестируемость. Хуки упрощают изолированное тестирование отдельных функций и компонентов.
- Оптимизация производительности. Такие хуки, как
useCallback
иuseMemo
, повышают производительность за счет запоминания значений и предотвращения ненужного повторного рендеринга.
Крюк useEffect
Хук useEffect
используется для выполнения побочных эффектов в функциональных компонентах. Побочные эффекты могут включать выборку данных, подписки или ручное изменение модели DOM. Хук принимает два аргумента: функцию и массив зависимостей.
Когда компонент визуализируется, функция, переданная в useEffect
, выполняется. По умолчанию он запускается после каждого рендера. Однако, указав зависимости в массиве, вы можете контролировать время выполнения эффекта. Если зависимости между рендерингами остаются прежними, эффект больше не запустится.
import React, { useState, useEffect } from 'react'; import axios from 'axios'; const DataComponent = ({ id }) => { const [data, setData] = useState(null); useEffect(() => { // Fetch data from the API when the component first renders const fetchData = async () => { try { const response = await axios.get(`/api/data/${id}`); setData(response.data); } catch (error) { // Handle error if the API request fails console.error('Error fetching data:', error); } }; fetchData(); }, [id]); useEffect(() => { // Update the component when the 'id' prop changes const handlePropChange = () => { // Perform specific logical actions based on the 'id' prop if (id === 'some-value') { // Do something } else { // Do something else } }; handlePropChange(); // Cleanup function return () => { // Perform cleanup actions when the component unmounts or 'id' prop changes if (id === 'cleanup-value') { // Perform specific cleanup logic // ... } else { // Perform different cleanup logic // ... } }; }, [id]); return ( <div> {/* Render the fetched data */} {data ? ( <div>{data}</div> ) : ( <div>Loading data...</div> )} </div> ); };
В приведенном выше примере блока кода DataComponent
извлекает данные из API при первом рендеринге с помощью хука useEffect
. Функция эффекта определена в хуке useEffect
и выполняет асинхронный вызов для получения данных. После успешного извлечения данных они сохраняются в состоянии компонента с помощью функции setData
.
Хук useEffect
также принимает массив зависимостей [id]
, который указывает, что эффект должен запускаться повторно при каждом изменении реквизита id
. Это гарантирует, что компонент будет обновляться новыми данными при каждом изменении свойства id
.
Кроме того, пример демонстрирует использование функции очистки в хуке useEffect
. Функция очистки выполняется, когда компонент размонтируется или когда изменяется свойство id
. Он позволяет выполнять любую необходимую очистку, например отменять ожидающие запросы или отписываться от прослушивателей событий.
Используя хук useEffect
, вы можете обрабатывать побочные эффекты, такие как выборка данных, декларативным и контролируемым образом, гарантируя, что компонент будет обновляться с последними данными и выполнять необходимую очистку, когда это необходимо.
Распространенные варианты использования
- Извлечение данных. Используйте
useEffect
для получения данных из API при монтировании компонента или при изменении определенных зависимостей. - Подписки. Управляйте подписками на внешние источники данных или генераторы событий с помощью
useEffect
. - Манипулирование DOM: если вам нужно напрямую взаимодействовать с DOM,
useEffect
— правильный хук.
Крюк useCallback
Хук useCallback
используется для запоминания функций и предотвращения ненужного повторного рендеринга в дочерних компонентах. Он возвращает запомненную версию функции обратного вызова, которая изменяется только в случае изменения одной из зависимостей. Это полезно при передаче обратных вызовов дочерним компонентам, чтобы предотвратить их повторный рендеринг без необходимости.
Когда компонент визуализируется, функции, определенные внутри него, создаются заново, что приводит к потенциальным проблемам с производительностью в дочерних компонентах, которые полагаются на эти функции.
Используя useCallback
, вы можете запомнить функцию и гарантировать, что она будет воссоздана только при изменении ее зависимостей. Эта оптимизация может значительно повысить производительность вашего приложения, особенно в сценариях, где обратные вызовы передаются на несколько уровней дерева компонентов.
import React, { useCallback } from 'react'; import ChildComponent from './ChildComponent'; const ParentComponent = () => { const handleClick = useCallback((itemId) => { // Perform specific action based on the itemId if (itemId % 2 === 0) { console.log(`Item with ID ${itemId} is even.`); } else { console.log(`Item with ID ${itemId} is odd.`); } }, []); return ( <div> {items.map((item) => ( <ChildComponent key={item.id} item={item} onClick={handleClick} /> ))} </div> ); };
В приведенном выше примере функция handleClick
внутри хука useCallback
выполняет логическое действие на основе itemId
. В этом случае он проверяет, является ли число itemId
четным или нечетным, и выводит соответствующее сообщение на консоль.
Запоминая функцию handleClick
с помощью useCallback
, вы гарантируете, что она воссоздается только при изменении ее зависимостей (в этом случае нет никаких зависимостей, указанных пустым массивом зависимостей []
). Эта оптимизация предотвращает ненужный повторный рендеринг дочерних компонентов и повышает производительность.
Затем запомненная функция handleClick
может быть передана в качестве реквизита экземплярам ChildComponent
, позволяя им запускать логическое действие при нажатии соответствующей кнопки.
Распространенные варианты использования
- Оптимизация дочерних компонентов. Используйте
useCallback
, чтобы предотвратить ненужный повторный рендеринг дочерних компонентов, которые полагаются на ссылки на функции для свойств. - Обработчики событий. При передаче обработчиков событий в качестве свойств или действий, таких как действия onClick,
useCallback
гарантирует, что ссылка остается стабильной, предотвращая ненужные повторные рендеринг.
Крюк useMemo
Хук useMemo
похож на useCallback
, но вместо запоминания функций он запоминает значения.
Он используется для запоминания значений и предотвращения ненужных повторных вычислений. Он принимает функцию и массив зависимостей в качестве аргументов. Функция, переданная useMemo
, будет пересчитывать запомненное значение только при изменении одной из зависимостей. Это полезно для оптимизации дорогостоящих вычислений или сложных операций.
import React, { useMemo } from 'react'; const ItemList = ({ data, options }) => { const expensiveCalculationResult = useMemo(() => { // Perform complex and computationally expensive calculation let result = []; for (let i = 0; i < data.length; i++) { // Perform some intensive operations on each item // ... // Example: Concatenate the item name with the options value const modifiedItem = { ...data[i], nameWithOptions: `${data[i].name} - ${options}`, }; result.push(modifiedItem); } return result; // The calculated result }, [data, options]); return ( <div> {expensiveCalculationResult.map((item) => ( <div key={item.id}>{item.nameWithOptions}</div> ))} </div> ); };
В приведенном выше примере expensiveCalculationResult
вычисляется внутри функции useMemo
. Расчет включает в себя повторение каждого элемента в массиве data
и выполнение некоторых интенсивных операций над каждым элементом. В этом случае в примере показано, как соединить имя элемента со значением переменной options
.
При запоминании результата с помощью useMemo
ресурсоемкий расчет будет выполняться снова, только если изменятся зависимости data
или options
. В противном случае будет возвращен ранее запомненный результат, что позволит избежать лишних вычислений и повысить производительность компонента.
Распространенные варианты использования
- Дорогие вычисления. Используйте
useMemo
, чтобы избежать избыточных вычислений, которые требуют больших вычислительных ресурсов. - Кэширование значений. Если значение не меняется часто и его вычисление требует больших ресурсов,
useMemo
может кэшировать результат до тех пор, пока не изменятся зависимости.
Различия между useEffect
, useCallback
и useMemo
Хотя useEffect
, useCallback
и useMemo
— это хуки, используемые в React, они служат разным целям:
useEffect
используется для обработки побочных эффектов и выполняется после каждого рендера.useCallback
используется в основном для запоминания функций и предотвращения ненужного повторного рендеринга в дочерних компонентах.useMemo
используется для запоминания значений и оптимизации дорогостоящих вычислений или сложных операций.
Эти хуки имеют разные варианты использования и должны выбираться в зависимости от конкретных требований вашего приложения.
Ключевые выводы
Чтобы максимально использовать эти хуки, рассмотрите следующие рекомендации:
- Используйте
useEffect
для получения данных, подписок и других побочных эффектов. - Используйте
useCallback
при передаче обратных вызовов дочерним компонентам, чтобы предотвратить ненужный повторный рендеринг. - Используйте
useMemo
для оптимизации дорогостоящих вычислений или сложных операций. - Тщательно выбирайте зависимости для каждого хука, чтобы убедиться, что они точны и актуальны.
- Избегайте ненужных повторных рендеров, используя соответствующий хук для каждого сценария.
Понимание разницы между хуками useEffect
, useCallback
и useMemo
имеет решающее значение для нас, разработчиков React. Эти хуки предоставляют мощные инструменты для управления состоянием, побочными эффектами и оптимизацией производительности. Используя правый хук в соответствующем сценарии, вы можете писать более чистый и эффективный код и улучшать общий пользовательский интерфейс ваших приложений React.