Реагировать на useEffect
крючки
Хук useEffect
позволяет вам выполнять побочные эффекты в ваших компонентах.
Некоторые примеры побочных эффектов: выборка данных, прямое обновление DOM и таймеры.
useEffect
принимает два аргумента. Второй аргумент является необязательным.
useEffect(<function>, <dependency>)
Давайте использовать таймер в качестве примера.
Пример:
Используйте setTimeout()
для подсчета 1 секунды после первоначального рендеринга:
import { useState, useEffect } from "react";
import ReactDOM from "react-dom";
function Timer() {
const [count, setCount] = useState(0);
useEffect(() => {
setTimeout(() => {
setCount((count) => count + 1);
}, 1000);
});
return <h1>I've rendered {count} times!</h1>;
}
ReactDOM.render(<Timer />, document.getElementById('root'));
Но ждать!! Я продолжаю считать, хотя это должно считаться только один раз!
useEffect
запускается при каждом рендере. Это означает, что при изменении счетчика происходит рендеринг, который запускает другой эффект.
Это не то, чего мы хотим. Есть несколько способов контролировать запуск побочных эффектов.
Мы всегда должны включать второй параметр, который принимает массив. При желании мы можем передать зависимости useEffect
в этот массив.
1. Зависимость не прошла:
useEffect(() => {
//Runs on every render
});
2. Пустой массив:
useEffect(() => {
//Runs only on the first render
}, []);
3. Пропсы или значения состояния:
useEffect(() => {
//Runs on the first render
//And any time any dependency value changes
}, [prop, state]);
Итак, чтобы решить эту проблему, давайте запустим этот эффект только на начальном рендере.
Пример:
Запускайте эффект только на начальном рендере:
import { useState, useEffect } from "react";
import ReactDOM from "react-dom";
function Timer() {
const [count, setCount] = useState(0);
useEffect(() => {
setTimeout(() => {
setCount((count) => count + 1);
}, 1000);
}, []); // <- add empty brackets here
return <h1>I've rendered {count} times!</h1>;
}
ReactDOM.render(<Timer />, document.getElementById('root'));
Пример:
Вот пример useEffect
хука, который зависит от переменной. Если count
переменная обновится, эффект запустится снова:
import { useState, useEffect } from "react";
import ReactDOM from "react-dom";
function Counter() {
const [count, setCount] = useState(0);
const [calculation, setCalculation] = useState(0);
useEffect(() => {
setCalculation(() => count * 2);
}, [count]); // <- add the count variable here
return (
<>
<p>Count: {count}</p>
<button onClick={() => setCount((c) => c + 1)}>+</button>
<p>Calculation: {calculation}</p>
</>
);
}
ReactDOM.render(<Counter />, document.getElementById('root'));
Если есть несколько зависимостей, они должны быть включены в useEffect
массив зависимостей.
Получите сертификат!
ЗАПИСАТЬСЯ НА 95 $
Очистка эффекта
Некоторые эффекты требуют очистки, чтобы уменьшить утечки памяти.
Тайм-ауты, подписки, прослушиватели событий и другие эффекты, которые больше не нужны, должны быть удалены.
Мы делаем это, включив функцию возврата в конце useEffect
хука.
Пример:
Очистите таймер в конце useEffect
хука:
import { useState, useEffect } from "react";
import ReactDOM from "react-dom";
function Timer() {
const [count, setCount] = useState(0);
useEffect(() => {
let timer = setTimeout(() => {
setCount((count) => count + 1);
}, 1000);
return () => clearTimeout(timer)
}, []);
return <h1>I've rendered {count} times!</h1>;
}
ReactDOM.render(<Timer />, document.getElementById("root"));
Примечание. Чтобы очистить таймер, нам нужно было дать ему имя.