В приложениях на Inferno управление состояниями загрузки и обработки ошибок является ключевым аспектом для создания отзывчивого и стабильного интерфейса. Это достигается сочетанием состояний компонентов, условного рендеринга и обработки исключений в асинхронных функциях.
Состояние загрузки обычно хранится в локальном состоянии
компонента с использованием useState. Стандартный
паттерн включает три состояния:
Пример реализации:
import { useState, useEffect } from 'inferno-hooks';
function DataLoader({ fetchData }) {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
fetchData()
.then(response => {
setData(response);
setLoading(false);
})
.catch(err => {
setError(err);
setLoading(false);
});
}, [fetchData]);
if (loading) {
return <div>Загрузка...</div>;
}
if (error) {
return <div>Ошибка: {error.message}</div>;
}
return <div>Данные: {JSON.stringify(data)}</div>;
}
Ключевые моменты:
useState используется для хранения состояния загрузки,
данных и ошибок.useEffect позволяет выполнять асинхронные запросы при
монтировании компонента.Для асинхронных запросов в Inferno чаще всего используют
fetch API или сторонние библиотеки вроде
Axios. Любой промис должен содержать блок
.catch для перехвата ошибок. Альтернатива — использование
async/await с конструкцией try/catch:
async function loadUserData() {
try {
const response = await fetch('/api/user');
if (!response.ok) throw new Error('Сетевая ошибка');
const result = await response.json();
return result;
} catch (err) {
console.error('Ошибка при загрузке данных:', err);
throw err;
}
}
Использование такого подхода обеспечивает:
Inferno поддерживает паттерн Error Boundaries,
который позволяет перехватывать ошибки в дочерних компонентах и
предотвращать крах всего приложения. Реализация включает метод
componentDidCatch в классовых компонентах:
import { Component } from 'inferno';
class ErrorBoundary extends Component {
constructor(props) {
super(props);
this.state = { hasError: false, error: null };
}
componentDidCatch(error) {
this.setState({ hasError: true, error });
console.error('Ошибка в компоненте:', error);
}
render() {
if (this.state.hasError) {
return <div>Произошла ошибка: {this.state.error.message}</div>;
}
return this.props.children;
}
}
Особенности:
try/catch).Для улучшения взаимодействия с пользователем часто используют скелетоны или индикаторы прогресса:
function SkeletonLoader({ width, height }) {
return (
<div style={{
width: width || '100%',
height: height || '1em',
backgroundColor: '#eee',
borderRadius: '4px',
animation: 'pulse 1.5s infinite'
}} />
);
}
pulse создается с помощью CSS для плавного
эффекта.Частой практикой является объединение логики загрузки и обработки ошибок в один контейнерный компонент:
function AsyncContainer({ fetchData, children }) {
const [state, setState] = useState({ data: null, loading: true, error: null });
useEffect(() => {
fetchData()
.then(data => setState({ data, loading: false, error: null }))
.catch(error => setState({ data: null, loading: false, error }));
}, [fetchData]);
if (state.loading) return <SkeletonLoader />;
if (state.error) return <div>Ошибка: {state.error.message}</div>;
return children(state.data);
}
Преимущества такого подхода:
try/catch или
.catch для корректного перехвата ошибок.