Publie le 24 mars 2026 Par

Consommer une API REST en JavaScript : fetch, Axios, gestion des erreurs

Presque toutes les applications web modernes consomment des APIs REST. Fetch, Axios, React Query — il y a plusieurs façons de le faire, et toutes ont leurs cas d’usage. Ce guide couvre les patterns essentiels : faire des requêtes, gérer les erreurs, authentifier, et structurer son code d’API de façon maintenable.

Fetch API — les bases

// GET — récupérer des données
const response = await fetch('/api/users')
if (!response.ok) throw new Error(`HTTP ${response.status}`)
const users = await response.json()

// POST — envoyer des données
const response = await fetch('/api/users', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ name: 'Alice', email: 'alice@example.com' }),
})
const newUser = await response.json()

// PUT/PATCH — mettre à jour
const response = await fetch(`/api/users/${id}`, {
  method: 'PATCH',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ name: 'Alice Updated' }),
})

// DELETE
await fetch(`/api/users/${id}`, { method: 'DELETE' })

Créer une couche d’abstraction API

Ne pas appeler fetch directement partout dans votre code. Créez une fonction centrale qui gère les headers communs, les erreurs, et l’authentification :

// lib/api.ts
const BASE_URL = process.env.NEXT_PUBLIC_API_URL || '/api'

class ApiError extends Error {
  constructor(public status: number, message: string) {
    super(message)
    this.name = 'ApiError'
  }
}

async function apiFetch(endpoint: string, options?: RequestInit): Promise {
  const token = localStorage.getItem('auth_token')

  const response = await fetch(`${BASE_URL}${endpoint}`, {
    ...options,
    headers: {
      'Content-Type': 'application/json',
      ...(token ? { Authorization: `Bearer ${token}` } : {}),
      ...options?.headers,
    },
  })

  if (!response.ok) {
    const error = await response.json().catch(() => ({ message: 'Erreur serveur' }))
    throw new ApiError(response.status, error.message)
  }

  return response.json()
}

// API typée
export const api = {
  get: (url: string) => apiFetch(url),
  post: (url: string, data: unknown) =>
    apiFetch(url, { method: 'POST', body: JSON.stringify(data) }),
  patch: (url: string, data: unknown) =>
    apiFetch(url, { method: 'PATCH', body: JSON.stringify(data) }),
  delete: (url: string) => apiFetch(url, { method: 'DELETE' }),
}

// Usage
const users = await api.get('/users')
const newUser = await api.post('/users', { name: 'Bob' })

Axios — quand l’utiliser

Axios reste pertinent pour ses fonctionnalités supplémentaires : intercepteurs, timeout configurable, upload de fichiers avec progress, annulation de requêtes simplifiée.

import axios from 'axios'

// Instance avec config partagée
const apiClient = axios.create({
  baseURL: process.env.NEXT_PUBLIC_API_URL,
  timeout: 10000,
})

// Intercepteur — ajouter le token à toutes les requêtes
apiClient.interceptors.request.use(config => {
  const token = localStorage.getItem('auth_token')
  if (token) config.headers.Authorization = `Bearer ${token}`
  return config
})

// Intercepteur — gérer les 401 globalement
apiClient.interceptors.response.use(
  response => response,
  error => {
    if (error.response?.status === 401) {
      // Rediriger vers login, refresh token, etc.
      redirectToLogin()
    }
    return Promise.reject(error)
  }
)

// Axios parse automatiquement le JSON et throw sur les erreurs HTTP
const { data: users } = await apiClient.get('/users')

React Query — la solution complète

Pour les applications React, React Query (TanStack Query) gère bien plus que le simple fetch : cache, synchronisation en arrière-plan, loading/error state, pagination, mutations.

// Installation
npm install @tanstack/react-query

// Setup dans _app.tsx ou layout.tsx
const queryClient = new QueryClient()

  


// Fetcher des données
function UserList() {
  const { data: users, isLoading, error } = useQuery({
    queryKey: ['users'],
    queryFn: () => api.get('/users'),
    staleTime: 5 * 60 * 1000, // données fraîches pendant 5 minutes
  })

  if (isLoading) return 
  if (error) return 
  return 
    {users.map(u =>
  • {u.name}
  • )}
} // Mutations function CreateUserForm() { const queryClient = useQueryClient() const mutation = useMutation({ mutationFn: (data: CreateUserDto) => api.post('/users', data), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['users'] }) // re-fetch la liste }, }) return (
{ e.preventDefault() mutation.mutate({ name: 'Alice' }) }}>
) }

Gestion des erreurs — les patterns

// Pattern 1 : Error Boundary pour les erreurs de rendu
// Pattern 2 : état local d'erreur pour les requêtes

// Distinguer les types d'erreurs
try {
  const user = await api.get(`/users/${id}`)
} catch (error) {
  if (error instanceof ApiError) {
    if (error.status === 404) showNotFound()
    else if (error.status === 403) showForbidden()
    else showGenericError(error.message)
  } else {
    // Erreur réseau — pas de connexion
    showNetworkError()
  }
}

Offres développeur JavaScript et React

Des postes pour développeurs qui savent intégrer des APIs et structurer des couches de données propres.

À lire aussi : JavaScript asynchroneHooks ReactTypeScript

Categories : JavaScript & React