首頁  >  文章  >  web前端  >  使用 Axios 和 React Query 回應 CRUD 操作

使用 Axios 和 React Query 回應 CRUD 操作

Patricia Arquette
Patricia Arquette原創
2024-09-24 20:30:40361瀏覽

React CRUD Operations with Axios and React Query

在上一篇文章《使用自訂 Hooks 簡化 React 中的 HTTP 請求? 》中,我們探討如何使用自訂 Hooks 簡化 HTTP 請求。雖然對於較小的應用程式有效,但隨著 React 應用程式的擴展,這種方法可能會變得更難以維護。在本文中,我們將深入探討如何使用 Axios 和 React Query 以可擴展的方式處理 CRUD(建立、讀取、更新、刪除)操作。

為什麼選擇 Axios 和 React Query?

  • Axios:適用於瀏覽器和 Node.js 的基於 Promise 的 HTTP 用戶端,Axios 使用乾淨、可讀的程式碼簡化了向 REST 端點發送非同步 HTTP 請求的過程。

  • React Query:一個強大的資料擷取庫,可增強 React 中的資料同步、快取和狀態管理。 React Query 可自動取得數據,同時提供對載入和錯誤狀態的更好控制。

設定 Axios 和 React 查詢

首先,安裝必要的軟體包:

npm install axios react-query react-router-dom

在您的應用程式中設定 React 查詢

接下來,在入口檔案 (App.tsx) 中設定 React Query 來管理應用程式的全域查詢設定。

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

使用攔截器設定 Axios

要處理全域身份驗證,我們可以建立一個 Axios 實例並使用攔截器為經過驗證的請求附加 Authorization 標頭。

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

為 CRUD 操作建立 API 函數

讓我們定義與 API 互動的函數,以使用 Axios 執行 CRUD 操作:

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

使用 React Query Hooks 進行 CRUD 操作

現在我們有了 API 函數,我們可以使用 React Query 來處理這些操作的狀態管理和資料擷取。

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

在元件中使用 CRUD 掛鉤

最後,我們可以建立一個簡單的元件,它使用自訂掛鉤並允許使用者建立、編輯和刪除貼文。

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

結論

透過使用 Axios 和 React Query,您可以簡化 React 應用程式中的 CRUD 操作。這種組合會產生乾淨、可維護的程式碼,從而提高可擴充性和效能。隨著應用程式的成長,使用這些工具可以簡化狀態管理和資料擷取。

有關 React、TypeScript 和現代 Web 開發實踐的更多見解,請在 Dev.to 上關注我! ?‍?

以上是使用 Axios 和 React Query 回應 CRUD 操作的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn