В приложениях на Inferno управление побочными эффектами играет ключевую роль, поскольку фреймворк ориентирован на высокую производительность и минимизацию ненужных перерисовок. Побочные эффекты — это любые действия, которые выходят за пределы чистого рендеринга компонентов: запросы к серверу, работа с локальным хранилищем, подписки на события, таймеры и манипуляции с DOM вне виртуального дерева.
Inferno поддерживает концепцию хуков, аналогичных
React, включая useEffect и useLayoutEffect.
Хуки позволяют организовать код так, чтобы побочные эффекты выполнялись
в строго определенные моменты жизненного цикла компонента.
Пример использования useEffect:
import { useEffect, useState } from 'inferno-hooks';
function Timer() {
const [count, setCount] = useState(0);
useEffect(() => {
const interval = setInterval(() => {
setCount(prev => prev + 1);
}, 1000);
return () => clearInterval(interval);
}, []);
return <div>Секунды: {count}</div>;
}
В этом примере эффект создаёт интервал, который обновляет состояние каждую секунду, и очищается при размонтировании компонента, предотвращая утечки памяти.
Одним из частых источников ошибок является неправильная очистка побочных эффектов. Все эффекты, создающие подписки, таймеры или слушатели событий, должны возвращать функцию очистки:
useEffect(() => {
function onResize() {
console.log(window.innerWidth);
}
window.addEventListener('resize', onResize);
return () => {
window.removeEventListener('resize', onResize);
};
}, []);
Важно: отсутствие функции очистки приводит к накоплению слушателей и росту нагрузки на память.
Вторым критически важным аспектом является массив
зависимостей, который указывается вторым аргументом в
useEffect или useLayoutEffect. Inferno
сравнивает значения зависимостей между рендерами и выполняет эффект
только при их изменении.
Пример контроля зависимостей:
useEffect(() => {
console.log(`Текущее значение count: ${count}`);
}, [count]);
В данном случае эффект будет вызываться только тогда, когда
count изменится, предотвращая лишние вызовы.
Асинхронные операции должны обрабатываться аккуратно. Если в эффекте
выполняется fetch, важно учитывать, что компонент может
быть размонтирован до завершения запроса. Для предотвращения состояния
гонки применяют флаг отмены:
useEffect(() => {
let cancelled = false;
async function fetchData() {
const response = await fetch('https://api.example.com/data');
const data = await response.json();
if (!cancelled) {
setData(data);
}
}
fetchData();
return () => {
cancelled = true;
};
}, []);
Такой подход предотвращает попытки обновления состояния у размонтированного компонента.
useLayoutEffect.
Этот хук блокирует рендер, поэтому тяжелые вычисления лучше выполнять в
useEffect.useCallback и useMemo для предотвращения
лишнего срабатывания эффектов.Иногда побочные эффекты касаются глобального состояния приложения, например, логирования, аналитики или работы с WebSocket. В таких случаях можно создать отдельный компонент-обработчик эффектов, который монтируется один раз и управляет глобальными эффектами:
function GlobalEffects() {
useEffect(() => {
const socket = new WebSocket('wss://example.com');
socket.onmess age = event => console.log(event.data);
return () => socket.close();
}, []);
return null;
}
Это помогает централизованно управлять жизненным циклом внешних ресурсов.
useEffect и
useLayoutEffect помогает избегать лишних рендеров и утечек
памяти.Эти принципы позволяют создавать приложения на Inferno с предсказуемым поведением, высокой производительностью и устойчивостью к ошибкам, связанным с побочными эффектами.