Представьте себе следующее: вы впервые создаете приложение React - вы рисуете каркас и пытаетесь представить себе, как все страницы и компоненты будут сочетаться друг с другом, и понимаете, что некоторые из них должны нести немного большую нагрузку, чем другие. В то время как некоторые компоненты должны только отображать свои конкретные компоненты, другие могут потребовать немного больше функциональности, может быть, они получают данные, обновляют DOM или управляют таймером; в общем, если компонент делает что-то, кроме простого возврата части JSX, он выполняет побочные эффекты. К счастью, в React есть специальный хук для таких задач: useEffect().
Для демонстрации давайте создадим компонент, который подсчитывает клики.
Для начала вы вызовете useEffect() почти так же, как и вызов state в верхней части компонента:
import React, { useState, useEffect } from 'react';
Далее мы создадим остальную часть компонента, направляя ему именно то, что мы хотим, чтобы он производил:
function ExampleComponent() {
const [count, setCount] = useState(0);
useEffect(() => {
// This function will be called after every render
document.title = `You clicked ${count} times`;
});
return (
<div>
<p>You clicked {count} times.</p>
<button onClick={() => setCount(count + 1)}>Click me</button>
</div>
);
}
В приведенном выше примере наш компонент отображает счетчик, а также кнопку. При нажатии состояние кнопки увеличивается через ‘count’, а хук useEffect() при каждом рендере обновляет заголовок документа текущим значением count.
Как вы видите, при вызове useEffect() в качестве основного аргумента принимается функция (которая вызывается после каждого рендеринга) и соответствующим образом обновляет свойство ‘document.title’.
Обратите внимание, что у хука useEffect() нет дополнительных аргументов, поэтому он будет вызываться после каждого рендера. Если мы хотим, чтобы он вызывался только при изменении переменной ‘count’, мы можем просто передать ее в качестве второго аргумента, как показано ниже:
useEffect(() => {
document.title = `You clicked ${count} times!`;
}, [count]);
Это называется зависимостью, которая предотвращает бесконечный цикл перебора аргументов в коде. И хотя у нас есть возможность передавать зависимости через массивы, как мы сделали выше, мы также можем передавать пустые массивы через наши функции в качестве вторых аргументов, как показано ниже:
import React, { useState, useEffect } from 'react';
function ExampleComponent() {
const [data, setData] = useState([]);
useEffect(() => {
// This function will be called once on component mount
fetch('https://example.com/data')
.then(response => response.json())
.then(data => setData(data))
}, []);
return (
<ul>
{data.map(item => (
<li key={item.id}>{item.title}</li>
))}
</ul>
);
Используя пустой массив в качестве второго аргумента, мы сообщаем нашему компоненту, что хотим, чтобы побочный эффект выполнялся только при первом отображении нашего компонента, что еще раз предотвращает бесконечный цикл.
Не знаете, когда и как передавать зависимости через второй аргумент useEffect? Вот краткое руководство!
- useEffect(() => {}): Никаких зависимостей! Это означает, что побочный эффект будет выполняться каждый раз при рендеринге компонента.
- useEffect(() => {}, []): И снова пустой массив! Это говорит нашему компоненту, что мы хотим, чтобы побочный эффект запускался только при первом отображении.
- useEffect(() => {}, [variable1, variable2]): Этот элемент может показаться новым - это массив зависимостей с элементами, и он сообщает, что побочный эффект должен запускаться всякий раз, когда переменная(ые) изменяется(ются).
Хотя это лишь краткий обзор, хук useEffect() является бесценным инструментом, когда речь идет о том, чтобы сделать компоненты более динамичными и интерактивными, поскольку он позволяет им реагировать на изменения состояния, взаимодействие с пользователем или даже внешние события. Используя этот хук для управления побочными эффектами, можно оптимизировать функциональность ваших компонентов для обновления в реальном времени, взаимодействия с внешними источниками данных, управления анимацией и переходами и многого другого! Я надеюсь, что вы будете практиковать использование этого метода в своих приложениях React, чтобы понять, насколько мощными могут стать отдельные компоненты. Счастливого кодинга!