Maison  >  Article  >  interface Web  >  Réagissez aux opérations CRUD avec Axios et React Query

Réagissez aux opérations CRUD avec Axios et React Query

Patricia Arquette
Patricia Arquetteoriginal
2024-09-24 20:30:40247parcourir

React CRUD Operations with Axios and 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.

Pourquoi 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.

Configuration d'Axios et de React Query

Tout d'abord, installez les packages nécessaires :

npm install axios react-query react-router-dom

Configuration de la requête React dans votre application

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;

Configuration d'Axios avec des intercepteurs

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 };

Création de fonctions API pour les opérations CRUD

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}`);

Utilisation des hooks de requête React pour les opérations CRUD

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
  });
};

Consommer des hooks CRUD dans un composant

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;

Conclusion

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!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn