Im vorherigen Artikel „HTTP-Anfragen in React mit benutzerdefinierten Hooks vereinfachen?“ haben wir untersucht, wie man HTTP-Anfragen mithilfe benutzerdefinierter Hooks vereinfacht. Während dieser Ansatz für kleinere Anwendungen effektiv ist, kann es schwieriger werden, ihn beizubehalten, wenn Ihre React-App skaliert wird. In diesem Artikel befassen wir uns mit der skalierbaren Handhabung von CRUD-Vorgängen (Erstellen, Lesen, Aktualisieren, Löschen) mithilfe von Axios und React Query.
Axios: Als versprochener HTTP-Client für den Browser und Node.js vereinfacht Axios das Senden asynchroner HTTP-Anfragen an REST-Endpunkte mit sauberem, lesbarem Code.
React Query: Eine leistungsstarke Datenabrufbibliothek, die die Datensynchronisierung, das Caching und die Statusverwaltung in React verbessert. React Query automatisiert den Datenabruf und bietet gleichzeitig eine bessere Kontrolle über Lade- und Fehlerzustände.
Installieren Sie zunächst die erforderlichen Pakete:
npm install axios react-query react-router-dom
Als nächstes konfigurieren Sie React Query in Ihrer Eintragsdatei (App.tsx), um die globalen Abfrageeinstellungen Ihrer Anwendung zu verwalten.
// 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;
Um die Authentifizierung global abzuwickeln, können wir eine Axios-Instanz erstellen und Interceptoren verwenden, um den Authorization-Header für authentifizierte Anfragen anzuhängen.
// 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 };
Lassen Sie uns Funktionen definieren, die mit unserer API interagieren, um CRUD-Operationen mit Axios auszuführen:
// 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}`);
Da wir nun über API-Funktionen verfügen, können wir React Query verwenden, um die Statusverwaltung und den Datenabruf für diese Vorgänge zu übernehmen.
// 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 }); };
Schließlich können wir eine einfache Komponente erstellen, die die benutzerdefinierten Hooks nutzt und es Benutzern ermöglicht, Beiträge zu erstellen, zu bearbeiten und zu löschen.
// 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;
Durch die Verwendung von Axios und React Query können Sie CRUD-Vorgänge in Ihren React-Anwendungen optimieren. Diese Kombination führt zu sauberem, wartbarem Code und verbessert die Skalierbarkeit und Leistung. Verwenden Sie diese Tools, um die Statusverwaltung und den Datenabruf zu vereinfachen, wenn Ihre App wächst.
Für weitere Einblicke in React, TypeScript und moderne Webentwicklungspraktiken folgen Sie mir auf Dev.to! ??
Das obige ist der detaillierte Inhalt vonReagieren Sie auf CRUD-Operationen mit Axios und React Query. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!