Maison > Article > interface Web > Réagissez aux opérations CRUD avec Axios et React Query
Dans l'article précédent, Simplifier les requêtes HTTP dans React avec des hooks personnalisés ?, nous avons exploré comment simplifier les requêtes HTTP à l'aide de hooks personnalisés. Bien qu'efficace pour les petites applications, cette approche peut devenir plus difficile à maintenir à mesure que votre application React évolue. Dans cet article, nous verrons comment gérer les opérations CRUD (Créer, Lire, Mettre à jour, Supprimer) de manière évolutive à l'aide d'Axios et React Query.
Axios : client HTTP basé sur des promesses pour le navigateur et Node.js, Axios simplifie l'envoi de requêtes HTTP asynchrones aux points de terminaison REST avec un code propre et lisible.
React Query : une puissante bibliothèque de récupération de données qui améliore la synchronisation des données, la mise en cache et la gestion de l'état dans React. React Query automatise la récupération des données tout en offrant un meilleur contrôle sur les états de chargement et d'erreur.
Tout d'abord, installez les packages nécessaires :
npm install axios react-query react-router-dom
Ensuite, configurez React Query dans votre fichier d'entrée (App.tsx) pour gérer les paramètres de requête globaux de votre application.
// src/App.tsx import { QueryClient, QueryClientProvider } from 'react-query'; import { CustomRouter } from './Router'; const queryClient = new QueryClient({ defaultOptions: { queries: { refetchOnWindowFocus: false, // Prevent refetch on tab/window switch retry: 1, // Retry failed queries once }, }, }); const App: React.FC = () => ( <QueryClientProvider client={queryClient}> <CustomRouter /> </QueryClientProvider> ); export default App;
Pour gérer l'authentification de manière globale, nous pouvons créer une instance Axios et utiliser des intercepteurs pour attacher l'en-tête Authorization pour les demandes authentifiées.
// src/config/axiosApi.ts import axios from 'axios'; const authenticatedApi = axios.create({ baseURL: import.meta.env.VITE_BASE_URL, // Environment-specific base URL headers: { 'Content-Type': 'application/json', }, }); // Attach Authorization token to requests if present authenticatedApi.interceptors.request.use((config) => { const token = localStorage.getItem('crud-app-auth-token'); if (token) { config.headers.Authorization = `Bearer ${token}`; } return config; }); export { authenticatedApi };
Définissons les fonctions qui interagissent avec notre API pour effectuer des opérations CRUD à l'aide d'Axios :
// src/data/api/post.ts import { authenticatedApi } from '../../config/axiosApi'; // Error handler function to standardize error messages export const handleApiError = (error: any): never => { if (error.message === 'Network Error') { throw new Error('Network Error. Please try again later.'); } else if (error.response?.data?.error) { throw new Error(error.response.data.error); } else if (error.response) { throw new Error('A server error occurred.'); } else { throw new Error(error.message || 'An unknown error occurred.'); } }; // General function to handle API requests export const apiCall = async <T>( method: 'get' | 'post' | 'put' | 'delete', url: string, data?: any, ): Promise<T> => { try { const response = await authenticatedApi[method](url, data); return response.data; } catch (error) { throw handleApiError(error); } }; // CRUD functions for the post feed export const createPostApi = (post: any) => apiCall<any>('post', 'posts', post); export const getPostsApi = () => apiCall<any>('get', 'posts'); export const updatePostApi = (id: string, post: any) => apiCall<any>('put', `posts/${id}`, post); export const deletePostApi = (id: string) => apiCall<any>('delete', `posts/${id}`);
Maintenant que nous disposons des fonctions API, nous pouvons utiliser React Query pour gérer la gestion de l'état et la récupération des données pour ces opérations.
// src/data/hooks/post.ts import { useMutation, useQuery, useQueryClient } from 'react-query'; import { createPostApi, getPostsApi, updatePostApi, deletePostApi } from '../api/post'; // Custom hooks for CRUD operations export const useCreatePostApi = () => { const queryClient = useQueryClient(); return useMutation(createPostApi, { onSuccess: () => queryClient.invalidateQueries(['posts']), // Refetch posts after a new post is created }); }; export const useGetPostsApi = () => useQuery(['posts'], getPostsApi); export const useUpdatePostApi = () => { const queryClient = useQueryClient(); return useMutation(updatePostApi, { onSuccess: () => queryClient.invalidateQueries(['posts']), // Refetch posts after an update }); }; export const useDeletePostApi = () => { const queryClient = useQueryClient(); return useMutation(deletePostApi, { onSuccess: () => queryClient.invalidateQueries(['posts']), // Refetch posts after deletion }); };
Enfin, nous pouvons créer un composant simple qui utilise les hooks personnalisés et permet aux utilisateurs de créer, modifier et supprimer des publications.
// src/components/PostCard.tsx import React, { useState } from 'react'; import { useGetPostsApi, useDeletePostApi, useUpdatePostApi, useCreatePostApi } from '../data/hooks/post'; import { toast } from '../components/Toast'; // Assume a toast component exists const PostCard: React.FC = () => { const { data: posts, isLoading, error } = useGetPostsApi(); const deletePost = useDeletePostApi(); const updatePost = useUpdatePostApi(); const createPost = useCreatePostApi(); const [newPost, setNewPost] = useState({ title: '', content: '' }); const handleCreate = async () => { try { await createPost.mutateAsync(newPost); setNewPost({ title: '', content: '' }); toast.success('Post created successfully'); } catch (error) { toast.error(error.message); } }; const handleDelete = async (id: string) => { try { await deletePost.mutateAsync(id); toast.success('Post deleted successfully'); } catch (error) { toast.error(error.message); } }; const handleEdit = async (id: string, updatedPost: any) => { try { await updatePost.mutateAsync({ id, ...updatedPost }); toast.success('Post updated successfully'); } catch (error) { toast.error(error.message); } }; if (isLoading) return <div>Loading...</div>; if (error) return <div>Error: {error.message}</div>; return ( <div> <div> <input type="text" value={newPost.title} onChange={(e) => setNewPost({ ...newPost, title: e.target.value })} placeholder="Title" /> <input type="text" value={newPost.content} onChange={(e) => setNewPost({ ...newPost, content: e.target.value })} placeholder="Content" /> <button onClick={handleCreate} disabled={createPost.isLoading}> {createPost.isLoading ? 'Creating...' : 'Create Post'} </button> </div> {posts?.map((post: any) => ( <div key={post.id}> <h3>{post.title}</h3> <p>{post.content}</p> <button onClick={() => handleEdit(post.id, { title: 'Updated Title', content: 'Updated Content' })}> Edit </button> <button onClick={() => handleDelete(post.id)}> Delete </button> </div> ))} </div> ); }; export default PostCard;
En utilisant Axios et React Query, vous pouvez rationaliser les opérations CRUD dans vos applications React. Cette combinaison aboutit à un code propre et maintenable, améliorant l’évolutivité et les performances. Utilisez ces outils pour simplifier la gestion de l'état et la récupération des données à mesure que votre application se développe.
Pour plus d'informations sur React, TypeScript et les pratiques modernes de développement Web, suivez-moi sur Dev.to ! ??
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!