Комментарии (2)
🐱
claude-haiku-4.5PrepBro AI3 апр. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Как писать запросы к API в Frontend
Основные подходы в современной разработке
Для запросов к API я использую несколько проверенных методов, в зависимости от контекста проекта. Наиболее распространённый вариант — это использование встроенного Fetch API с дополнительными утилитами для обработки ошибок и типизации.
Fetch API с типизацией (TypeScript)
// lib/api.ts
interface ApiResponse<T> {
data: T;
status: number;
success: boolean;
}
async function fetchApi<T>(
url: string,
options?: RequestInit
): Promise<ApiResponse<T>> {
try {
const response = await fetch(`${process.env.NEXT_PUBLIC_API_URL}${url}`, {
headers: {
'Content-Type': 'application/json',
...options?.headers,
},
...options,
});
if (!response.ok) {
throw new Error(`API error: ${response.status}`);
}
const data = await response.json();
return {
data,
status: response.status,
success: true,
};
} catch (error) {
console.error('API request failed:', error);
return {
data: null as unknown as T,
status: 0,
success: false,
};
}
}
export const api = {
get: <T,>(url: string) => fetchApi<T>(url, { method: 'GET' }),
post: <T,>(url: string, body: unknown) =>
fetchApi<T>(url, { method: 'POST', body: JSON.stringify(body) }),
put: <T,>(url: string, body: unknown) =>
fetchApi<T>(url, { method: 'PUT', body: JSON.stringify(body) }),
};
Использование в компонентах (React)
// components/UserProfile.tsx
import { useEffect, useState } from 'react';
import { api } from '@/lib/api';
interface User {
id: string;
name: string;
email: string;
}
export function UserProfile() {
const [user, setUser] = useState<User | null>(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
useEffect(() => {
const fetchUser = async () => {
try {
const response = await api.get<User>('/users/me');
if (response.success) {
setUser(response.data);
} else {
setError('Failed to load user');
}
} catch (err) {
setError(err instanceof Error ? err.message : 'Unknown error');
} finally {
setLoading(false);
}
};
fetchUser();
}, []);
if (loading) return <div>Loading...</div>;
if (error) return <div className="text-red-600">{error}</div>;
if (!user) return <div>No user data</div>;
return (
<div className="p-4">
<h1>{user.name}</h1>
<p>{user.email}</p>
</div>
);
}
Работа с заголовками и аутентификацией
Для безопасной работы с токенами аутентификации нужно правильно управлять заголовками запроса:
// lib/api.ts
const getAuthToken = () => localStorage.getItem('authToken');
async function fetchApi<T>(
url: string,
options?: RequestInit
): Promise<ApiResponse<T>> {
const token = getAuthToken();
const headers: HeadersInit = {
'Content-Type': 'application/json',
...options?.headers,
};
if (token) {
headers['Authorization'] = `Bearer ${token}`;
}
// rest of implementation
}
Обработка разных типов ответов
Для работы с различными типами данных — изображениями, файлами, бинарными данными:
// Для работы с изображениями и файлами
async function fetchFile(url: string): Promise<Blob> {
const response = await fetch(url);
return response.blob();
}
// Для загрузки файлов
async function uploadFile(url: string, file: File): Promise<void> {
const formData = new FormData();
formData.append('file', file);
const response = await fetch(url, {
method: 'POST',
body: formData,
});
if (!response.ok) throw new Error('Upload failed');
}
Ключевые принципы: обработка ошибок на уровне приложения, использование типизации для безопасности, никогда не храним чувствительные данные в localStorage без защиты.