Preact, как лёгкая и высокопроизводительная альтернатива React,
предоставляет все базовые возможности для работы с внешними данными.
Основной способ взаимодействия с API — использование встроенного
fetch или сторонних библиотек, таких как Axios, в сочетании
с жизненным циклом компонентов и хуками.
fetch является нативным инструментом браузеров для
выполнения HTTP-запросов. В Preact его удобно использовать внутри хуков
useEffect, чтобы выполнять асинхронные операции при
монтировании компонента.
import { h } from 'preact';
import { useState, useEffect } from 'preact/hooks';
function DataFetcher() {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
fetch('https://api.example.com/items')
.then(response => {
if (!response.ok) {
throw new Error(`Ошибка: ${response.status}`);
}
return response.json();
})
.then(json => setData(json))
.catch(err => setError(err.message))
.finally(() => setLoading(false));
}, []);
if (loading) return <div>Загрузка...</div>;
if (error) return <div>{error}</div>;
return (
<ul>
{data.map(item => <li key={item.id}>{item.name}</li>)}
</ul>
);
}
Ключевые моменты:
useEffect с пустым массивом зависимостей выполняется
только один раз при монтировании.finally позволяет корректно управлять состоянием
загрузки независимо от результата запроса.catch обеспечивает устойчивость
приложения.Axios предоставляет удобный API для выполнения HTTP-запросов и автоматически обрабатывает JSON. Его синтаксис более лаконичен, особенно при работе с заголовками и конфигурациями.
import { h } from 'preact';
import { useState, useEffect } from 'preact/hooks';
import axios from 'axios';
function AxiosFetcher() {
const [items, setItems] = useState([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
const source = axios.CancelToken.source();
axios.get('https://api.example.com/items', { cancelToken: source.token })
.then(response => setItems(response.data))
.catch(err => {
if (!axios.isCancel(err)) {
setError(err.message);
}
})
.finally(() => setLoading(false));
return () => {
source.cancel('Компонент размонтирован');
};
}, []);
if (loading) return <div>Загрузка данных...</div>;
if (error) return <div>Ошибка: {error}</div>;
return (
<ul>
{items.map(item => <li key={item.id}>{item.name}</li>)}
</ul>
);
}
Особенности использования Axios в Preact:
Для повторного использования логики запросов можно создавать кастомные хуки:
import { useState, useEffect } from 'preact/hooks';
import axios from 'axios';
function useApi(url) {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
const source = axios.CancelToken.source();
axios.get(url, { cancelToken: source.token })
.then(response => setData(response.data))
.catch(err => {
if (!axios.isCancel(err)) setError(err.message);
})
.finally(() => setLoading(false));
return () => source.cancel();
}, [url]);
return { data, loading, error };
}
Использование:
function ItemsList() {
const { data, loading, error } = useApi('https://api.example.com/items');
if (loading) return <div>Загрузка...</div>;
if (error) return <div>Ошибка: {error}</div>;
return (
<ul>
{data.map(item => <li key={item.id}>{item.name}</li>)}
</ul>
);
}
Преимущества кастомного хука:
Для REST достаточно fetch или Axios, но для GraphQL
часто применяют Apollo Client или urql, которые позволяют управлять
кешированием и подписками.
Пример запроса через fetch для GraphQL:
const query = `
query {
items {
id
name
}
}
`;
fetch('https://api.example.com/graphql', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ query })
})
.then(res => res.json())
.then(res => console.log(res.data));
Особенности работы с GraphQL:
Использование async/await делает код более читаемым и
понятным:
useEffect(() => {
let isMounted = true;
async function fetchData() {
try {
const response = await fetch('https://api.example.com/items');
if (!response.ok) throw new Error('Ошибка сети');
const result = await response.json();
if (isMounted) setData(result);
} catch (err) {
if (isMounted) setError(err.message);
} finally {
if (isMounted) setLoading(false);
}
}
fetchData();
return () => { isMounted = false; };
}, []);
Важные моменты:
isMounted предотвращает изменение состояния после
размонтирования.async/await упрощает цепочки промисов и делает
обработку ошибок более прозрачной.Для сложных приложений с множественными API-запросами удобно сочетать Preact с глобальными стейт-менеджерами, такими как Redux или Zustand. Это позволяет хранить результаты запросов централизованно и уменьшает количество повторных обращений к API.
import create from 'zustand';
const useStore = create(set => ({
items: [],
fetchItems: async () => {
const response = await fetch('https://api.example.com/items');
const data = await response.json();
set({ items: data });
}
}));
function Items() {
const { items, fetchItems } = useStore();
useEffect(() => { fetchItems(); }, []);
return (
<ul>
{items.map(item => <li key={item.id}>{item.name}</li>)}
</ul>
);
}
Преимущества такого подхода:
Эти подходы обеспечивают гибкую и эффективную работу с API в Preact, сочетая минимализм фреймворка с современными практиками асинхронного программирования и управления состоянием.