BaliseTonSite

Génération de Hooks de Données

Crée des Custom Hooks de fetching et de mutation (SWR / React Query) par l'IA, du boilerplate zéro.

4.1Les sorts de convocation

Un hook de données, c'est comme un allié invoqué qui se charge de gérer une ressource pour toi. Tu appelles usePosts() et en échange, tu reçois les données, l'état de chargement et les erreurs, sans avoir écrit une seule ligne de fetch, useEffect ou useState.

4.2Générer un hook SWR depuis une spécification

Prompt : Hook SWR de fetchingmarkdown
Tu es un dev React/TypeScript senior.

Génère un custom hook "usePosts" qui :
- Fetch les articles depuis /wp-json/wp/v2/posts
- Utilise SWR pour le cache et la revalidation
- Supporte ces paramètres : page, perPage, categoryId, search (tous optionnels)
- Retourne : { posts, isLoading, isError, pagination }
- Valide les données avec le WpPostSchema Zod (importé depuis @/lib/types/schemas)
- Gère les erreurs réseau et les erreurs de validation séparément

Types d'entrée et de sortie stricts en TypeScript.
Le hook doit être pur, sans side effects autres que fetch.
Résultat : hooks/usePosts.ts générétypescript
import useSWR from 'swr';
import { z } from 'zod';
import { WpPostSchema } from '@/lib/types/schemas/post.schema';

const WpPostArraySchema = z.array(WpPostSchema);
type WpPost = z.infer<typeof WpPostSchema>;

interface UsePostsParams {
    page?: number;
    perPage?: number;
    categoryId?: number;
    search?: string;
}

interface UsePostsReturn {
    posts: WpPost[] | undefined;
    isLoading: boolean;
    isError: Error | null;
    pagination: { page: number; totalPages: number } | null;
}

function buildUrl(params: UsePostsParams): string {
    const url = new URL('/wp-json/wp/v2/posts', window.location.origin);
    url.searchParams.set('_embed', '1');
    if (params.page) url.searchParams.set('page', String(params.page));
    if (params.perPage) url.searchParams.set('per_page', String(params.perPage));
    if (params.categoryId) url.searchParams.set('categories', String(params.categoryId));
    if (params.search) url.searchParams.set('search', params.search);
    return url.toString();
}

async function fetcher(url: string) {
    const res = await fetch(url);
    if (!res.ok) throw new Error(`HTTP ${res.status}: ${res.statusText}`);
    
    const raw = await res.json();
    const parsed = WpPostArraySchema.safeParse(raw);
    
    if (!parsed.success) {
        throw new Error('Contrat API invalide: ' + parsed.error.message);
    }
    
    return {
        posts: parsed.data,
        totalPages: Number(res.headers.get('X-WP-TotalPages') ?? 1),
    };
}

export function usePosts(params: UsePostsParams = {}): UsePostsReturn {
    const url = buildUrl(params);
    const { data, error, isLoading } = useSWR(url, fetcher, {
        revalidateOnFocus: false,
        keepPreviousData: true,
    });

    return {
        posts: data?.posts,
        isLoading,
        isError: error ?? null,
        pagination: data ? { page: params.page ?? 1, totalPages: data.totalPages } : null,
    };
}

4.3Générer un hook de mutation React Query

Pour les mutations (créer, modifier, supprimer), React Query avec useMutation est le standard. Voici le prompt adapté :

Prompt : Hook useMutation React Querymarkdown
Génère un custom hook "useUpdatePost" avec React Query (@tanstack/react-query).

Action : PUT /wp-json/wp/v2/posts/:id
Corps : Partial<WpPost> (titre, contenu, statut seulement)
Auth : Bearer token dans le header (récupéré depuis useAuthStore - Zustand)

Le hook retourne :
- mutate(id, data) - déclenche la mutation
- isLoading, isSuccess, isError, error
- Invalide le cache SWR de la liste des posts après succès

Gestion d'erreurs : distingue 401 (non autorisé), 404 (introuvable), 422 (validation).
Résultat : hooks/useUpdatePost.ts générétypescript
import { useMutation, useQueryClient } from '@tanstack/react-query';
import { useAuthStore } from '@/lib/stores/auth-store';
import type { WpPost } from '@/lib/types/schemas/post.schema';

type UpdatePostInput = {
    id: number;
    data: Pick<Partial<WpPost>, 'title' | 'content' | 'status'>;
};

class ApiError extends Error {
    constructor(public status: number, message: string) {
        super(message);
    }
}

async function updatePost({ id, data }: UpdatePostInput, token: string): Promise<WpPost> {
    const res = await fetch(`/wp-json/wp/v2/posts/${id}`, {
        method: 'PUT',
        headers: { 
            'Content-Type': 'application/json',
            'Authorization': `Bearer ${token}`,
        },
        body: JSON.stringify(data),
    });

    if (res.status === 401) throw new ApiError(401, 'Session expirée, reconnecte-toi.');
    if (res.status === 404) throw new ApiError(404, 'Article introuvable.');
    if (res.status === 422) throw new ApiError(422, 'Données invalides.');
    if (!res.ok) throw new ApiError(res.status, 'Erreur serveur.');

    return res.json();
}

export function useUpdatePost() {
    const queryClient = useQueryClient();
    const token = useAuthStore((s) => s.token);

    return useMutation({
        mutationFn: (input: UpdatePostInput) => updatePost(input, token ?? ''),
        onSuccess: () => {
            queryClient.invalidateQueries({ queryKey: ['posts'] });
        },
    });
}

Génération en lot

Pour générer tous tes hooks d'un coup, donne à l'IA ta liste d'endpoints avec leurs méthodes et types, et demande-lui de créer un fichier par ressource. Tu passes de 2h de boilerplate à 5 minutes.

Prompt lotmarkdown
Génère un hook SWR [de lecture] pour chacun de ces endpoints :
- GET /wp/v2/posts → list + single
- GET /wp/v2/categories → list
- GET /wp/v2/users/me → profil connecté

Utilise le même pattern fetcher + Zod que le hook usePosts que je t'ai montré.

Verifie tes acquis

5 questions pour valider ce chapitre

1. Comment demander à l'IA de créer un hook React custom ?

Valide et sauvegarde ce chapitre

Ne perds pas le fil de ton apprentissage. Chaque QCM terminé sauvegarde ton score. Crée ton profil gratuitement pour débloquer toutes les évaluations du site et retrouver tes résultats plus tard.

Commencer l'aventure
Déjà membre ?Connecte-toi