React Query Factory: قلاب های ایمن قابل استفاده مجدد با Axios & FSD

در دنیای مدرن توسعه Frontend ، بهینه سازی داده ها کلید ایجاد برنامه های پاسخگو و مقیاس پذیر است. استفاده از کتابخانه برای درخواست های ناهمزمان ، مانند @tanstack/react-query
وت axios
، یک سیستم مناسب برای کار با آن فراهم می کند REST APIs
با tRPC
، یا GraphQL
بشر
در هنگام تهیه برنامه ها ، ما اغلب باید اقدامات مشابهی را برای موجودات مختلف API انجام دهیم: لیستی از موارد را دریافت کنید ، یک مورد واحد را با شناسه بازیابی کنید ، یک مورد جدید ایجاد کنید و همچنین به روزرسانی ها و حذف ها را انجام دهید. این عملیات نامیده می شود CRUD
(ایجاد ، خواندن ، به روزرسانی ، حذف).
من نحوه اجرای قلاب های جهانی Crud را با استفاده از کتابخانه های فوق الذکر به سبک کاربردی بر اساس الگوی کارخانه نشان خواهم داد. به جای کپی کردن کد برای هر نهاد ، می توانیم قلاب هایی تولید کنیم که به طور قابل توجهی میزان کد کپی چسبانده را کاهش می دهد و آن را انعطاف پذیر و قابل استفاده مجدد می کند. این رویکرد به راحتی مقیاس پذیر ، جهانی و برای هر API قابل اجرا است.
می توانید این مقاله را در وبلاگ من بخوانید یا در اینجا بخوانید.
@tanstack/react-query و axios
-
@tanstack/react-query
-که قبلاً با عنوان React-Query شناخته می شد ، کتابخانه ای برای مدیریت وضعیت درخواست ها ، ذخیره کردن داده ها و همگام سازی آن با سرور است. این عملکرد را به طور قابل توجهی بهبود می بخشد و کار با درخواست های ناهمزمان را با انتزاع منطق API به دور از منطق ارائه داده ها در مؤلفه های React ساده می کند. -
axios
یک کتابخانه محبوب برای درخواست HTTP است. این امر به دلیل انعطاف پذیری و سهولت استفاده از جمله هنگام کار با عملیات ناهمزمان شناخته شده است.
هدف ما ایجاد تابعی است که به طور خودکار قلاب های Crud را برای هر نهاد ایجاد می کند و ما را از نوشتن همان کد بارها و بارها نجات می دهد. به عنوان مثال ، اگر ما نیاز به واکشی کاربران ، پست ها یا نظرات داریم ، نمی خواهیم همان کد دیگ بخار را برای هر نهاد تکرار کنیم.
اجرای قلاب های Crud به سبک عملکردی
بیایید با اجرای آن ادامه دهیم. ما یک تابع ایجاد خواهیم کرد createCrudHooks
این مجموعه ای از قلاب های Crud را برای هر موجودیت خاص برمی گرداند.
مرحله 1: کتابخانه های لازم را وصل کنید
برای رسیدگی به پرس و جو و حافظه پنهان ، نصب کنید @tanstack/react-query
وت axios
(بعد از جابجایی به فهرست پروژه خود):
cd ./my-awesome-project
npm i axios react-query
مرحله 2: عملکرد اصلی را ایجاد کنید
اکنون ایجاد کنید createCRUDHooks
عملکرد ، که یک URL پایه و یک نام موجودیت (به عنوان مثال کاربران یا پست ها) می گیرد. این تابع مجموعه ای از قلاب ها را برای انجام عملیات CRUD برمی گرداند.
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
import axios, { AxiosResponse } from 'axios'
const createCrudHooks = <T>(baseUrl: string, entity: string) => {
const api = axios.create({
baseURL: baseUrl,
})
// Fetch All (GET)
const useFetchAll = (queryKey: string) => {
return useQuery<T[]>(queryKey, async () => {
const response: AxiosResponse<T[]> = await api.get(`/${entity}`)
return response.data
})
}
// Fetch One by ID (GET)
const useFetchOne = (queryKey: string, id: string | number) => {
return useQuery<T>([queryKey, id], async () => {
const response: AxiosResponse<T> = await api.get(`/${entity}/${id}`)
return response.data
})
}
// Create (POST)
const useCreate = () => {
const queryClient = useQueryClient()
return useMutation(
async (data: Partial<T>) => {
const response: AxiosResponse<T> = await api.post(`/${entity}`, data)
return response.data
},
{
onSuccess: () => {
queryClient.invalidateQueries(entity)
},
}
)
}
// Update (PUT)
const useUpdate = () => {
const queryClient = useQueryClient()
return useMutation(
async ({ id, data }: { id: string | number; data: Partial<T> }) => {
const response: AxiosResponse<T> = await api.put(
`/${entity}/${id}`,
data
)
return response.data
},
{
onSuccess: () => {
queryClient.invalidateQueries(entity)
},
}
)
}
// Delete (DELETE)
const useDelete = () => {
const queryClient = useQueryClient()
return useMutation(
async (id: string | number) => {
const response: AxiosResponse<void> = await api.delete(
`/${entity}/${id}`
)
return response.data
},
{
onSuccess: () => {
queryClient.invalidateQueries(entity)
},
}
)
}
return {
useFetchAll,
useFetchOne,
useCreate,
useUpdate,
useDelete
}
}
می توانید اطلاعات بیشتر در مورد استفاده از نوع ایمن با @tanstack/react-query را در مقاله query React Retact-Safe بخوانید.
بیایید با جزئیات بیشتری بررسی کنیم که چه چیزی را قلاب می کند createCrudHooks
عملکرد برمی گردد:
HOOK USEFETCHALL
این قلاب برای بازیابی لیستی از موارد برای یک موجود خاص (به عنوان مثال ، لیستی از کاربران) درخواست دریافت می کند و از این استفاده می کند useQuery
قلاب از @tanstack/react-query
کتابخانه برای ذخیره و ردیابی وضعیت درخواست. این مجموعه از مواردی را که می تواند در هر مؤلفه React برای ارائه یا دستکاری بیشتر استفاده شود ، برمی گرداند. این تابع را می توان برای تصویب پارامترهای پرس و جو اضافی ، به عنوان مثال ، برای فیلتر کردن نتایج گسترش داد.
Hook UseFetchone
این قلاب توسط شناسه خود (شناسه منحصر به فرد) یک مورد واحد را بازیابی می کند. همچنین استفاده می کند useQuery
، اما یک استدلال دوم – شناسه مورد. این به شما امکان می دهد داده ها را برای یک مورد خاص موجودی دریافت کنید.
قلاب
این قلاب برای ایجاد موارد جدید استفاده می شود. این یک درخواست پست به API صادر می کند و پس از ایجاد موفقیت آمیز یک مورد ، تماس می گیرد invalidateQueries
برای تازه کردن حافظه پنهان ، بارگیری مجدد داده ها در سایر مؤلفه هایی که از قلاب های ما استفاده می شود ، بارگیری مجدد می شود.
HookeUpdate
از درخواست Put برای به روزرسانی یک مورد استفاده می شود. قلاب یک شیء حاوی شناسه مورد و داده ها را برای به روزرسانی می گیرد. پس از بروزرسانی موفق ، حافظه نهان داده نیز تازه می شود.
قلاب
این قلاب با استفاده از یک درخواست حذف ، یک مورد را توسط شناسه خود حذف می کند و پس از حذف ، حافظه پنهان داده را به روز می کند.
مرحله 3: تست ها
بیایید تست ها را اضافه کنیم تا اطمینان حاصل شود که کد ما به درستی و بدون خطا کار می کند.
ابتدا محیط آزمایش را با کتابخانه های زیر تنظیم کنید:
-
@testing-library/react
– برای آزمایش اجزای React. -
@testing-library/jest-dom
– تطابق اضافی را برای ادعاها فراهم می کند (به عنوان مثال ،toBeInTheDocument
). -
vitest
– یک دونده آزمون و چارچوبی برای نوشتن تست. -
axios-mock-adapter
– برای تمسخر درخواست ها از طریق Axios.
npm i @testing-library/react @testing-library/jest-dom vitest axios-mock-adapter -D
برای اجرای تست ها ، اسکریپت زیر را به آن اضافه کنید package.json
:
"scripts": {
"test": "vitest"
}
اکنون می توانید تست ها را اجرا کنید:
npm run test
برای مثال بیایید یک فایل آزمایش ایجاد کنیم crudHooks.test.tsx
:
import { QueryClient, QueryClientProvider } from 'react-query'
import { act, renderHook } from '@testing-library/react'
import axios from 'axios'
import MockAdapter from 'axios-mock-adapter'
// Your hooks
import { createCrudHooks } from './crudHooks'
const mock = new MockAdapter(axios)
const createTestQueryClient = () => {
return new QueryClient({
defaultOptions: {
queries: {
retry: false,
},
},
})
}
const wrapper = ({ children }: { children: React.ReactNode }) => {
const queryClient = createTestQueryClient()
return (
<QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
)
}
interface User {
id: number
name: string
email: string
}
// Create hooks for user entity
const { useFetchAll, useFetchOne, useCreate, useUpdate, useDelete } =
createCrudHooks<User>('https://api.example.io', 'users')
beforeEach(() => {
mock.reset()
})
describe('CRUD Hooks', () => {
it('should fetch all users successfully', async () => {
const mockData = [
{ id: 1, name: 'Ivan Green', email: 'ivan@example.io' },
{ id: 2, name: 'Inna Green', email: 'inna@example.io' },
]
mock.onGet('/users').reply(200, mockData)
const { result, waitFor } = renderHook(() => useFetchAll('users'), {
wrapper,
})
await waitFor(() => result.current.isSuccess)
expect(result.current.data).toEqual(mockData)
})
it('should fetch one user by ID', async () => {
const mockUser = { id: 1, name: 'Ivan Green', email: 'ivan@example.io' }
mock.onGet('/users/1').reply(200, mockUser)
const { result, waitFor } = renderHook(() => useFetchOne('users', 1), {
wrapper,
})
await waitFor(() => result.current.isSuccess)
expect(result.current.data).toEqual(mockUser)
})
it('should create a new user', async () => {
const newUser = { id: 3, name: 'Sam Smith', email: 'sam@example.io' }
mock.onPost('/users').reply(201, newUser)
const { result, waitFor } = renderHook(() => useCreate(), { wrapper })
act(() => {
result.current.mutate({ name: 'Sam Smith', email: 'sam@example.io' })
})
await waitFor(() => result.current.isSuccess)
expect(result.current.data).toEqual(newUser)
})
it('should update a user', async () => {
const updatedUser = {
id: 1,
name: 'Ivan Updated',
email: 'ivan.updated@example.io',
}
mock.onPut('/users/1').reply(200, updatedUser)
const { result, waitFor } = renderHook(() => useUpdate(), { wrapper })
act(() => {
result.current.mutate({
id: 1,
data: { name: 'Ivan Updated', email: 'Ivan.updated@example.io' },
})
})
await waitFor(() => result.current.isSuccess)
expect(result.current.data).toEqual(updatedUser)
})
it('should delete a user', async () => {
mock.onDelete('/users/1').reply(200)
const { result, waitFor } = renderHook(() => useDelete(), { wrapper })
act(() => {
result.current.mutate(1)
})
await waitFor(() => result.current.isSuccess)
expect(result.current.isSuccess).toBe(true)
})
})
ما با استفاده از مجموعه قلاب Crud خود تست هایی ایجاد کرده ایم react-testing-library
با axios-mock-adapter
وت vitest
بشر این باعث می شود کد ما قابل اعتماد و به خوبی آزمایش شده باشد ، که برای توسعه برنامه های مقیاس پذیر و قابل نگهداری مهم است. آزمایش عملیات ناهمزمان به لطف درخواست تمسخر و ابزاری برای کار با قلاب بسیار ساده تر می شود.
استفاده از مثال در یک مؤلفه React
اکنون که قلاب های جهانی را ایجاد کرده ایم ، بیایید ببینیم چگونه از آنها در یک مؤلفه واقعی استفاده کنیم:
interface User {
id: number
name: string
email: string
}
// Can be moved to a separate file for reuse
const { useFetchAll, useCreate, useUpdate, useDelete } = createCrudHooks<User>(
'https://api.example.io',
'users'
)
type UserProps = {
user: User
}
const UserItem = ({ user }: UserProps) => {
const { mutate: updateUser } = useUpdate()
const { mutate: deleteUser } = useDelete()
const handleUpdate = () => {
updateUser({ id: user.id, data: { name: 'Ivan' } })
}
const handleDelete = () => {
deleteUser(user.id)
}
return (
<li key={user.id}>
{user.name} - {user.email}
<button onClick={handleUpdate}>Update namebutton>
<button onClick={handleDelete}>Deletebutton>
li>
)
}
export const Users = () => {
const { data: users, isLoading } = useFetchAll('users')
const { mutate: createUser } = useCreate()
const handleCreateUser = () => {
createUser({ name: 'Darya', email: 'darya@example.io' })
}
if (isLoading) return <div>Loading users...div>
return (
<div>
<h1>Usersh1>
<ul>
{users?.map((user: User) => (
<UserItem key={user.id} user={user} />
))}
ul>
<button onClick={handleCreateUser}>Create userbutton>
div>
)
}
این رویکرد چه مشکلی دارد؟
هنگام استفاده از بسته بندی ها برای قلاب ، می توانید با شماره های تایپ همانطور که در این بحث GitHub توضیح داده شده است ، روبرو شوید. یکی از گزینه ها استفاده از کارخانه های پرس و جو است که در ادامه در نظر خواهیم گرفت. می توانید کارخانه خود را بنویسید یا از کارخانه کلید Query Query استفاده کنید.
نمونه ای از استفاده از یک کارخانه پرس و جو در یک برنامه ساخته شده بر روی اصول طراحی دارای ویژگی (FSD)
به عنوان یک مقیاس پروژه ، اطمینان از مدولار بودن و سازمان آن مهم می شود. یکی از رویکردهای معماری ، طراحی دارای ویژگی (FSD) است که به سازماندهی یک برنامه با عملکرد کمک می کند و لایه های مسئولیت را ترسیم می کند. بیایید نحوه استفاده FSD را در پروژه ای که استفاده می کند در نظر بگیریم @tanstack/react-query
بشر
طراحی دارای ویژگی چیست؟
FSD (طراحی با ویژگی) یک رویکرد معماری است که در آن یک برنامه بر اساس عملکرد به ماژول های مستقل (ویژگی ها) تقسیم می شود. هدف اصلی بهبود مقیاس پذیری ، حفظ و خوانایی پروژه است. FSD به جلوگیری از رشد کنترل نشده پایگاه کد کمک می کند و آزمایش را ساده می کند.
سطح FSD
- برنامه: تنظیمات جهانی ، مسیریابی و ارائه دهندگان.
- صفحات: صفحات کامل یا قسمتهای بزرگ یک صفحه برای مسیریابی تو در تو.
- ویراچه: قطعات بزرگ خودکشی از عملکرد یا رابط ، معمولاً اجرای یک سناریوی کل کاربر.
- ویژگی: اجرای قابل استفاده مجدد از ویژگی های کامل محصول ، یعنی اقداماتی که ارزش کسب و کار را به کاربر ارائه می دهد.
- موجودات: اشیاء منطقی منطقی تجارت ، مانند کاربران ، سفارشات و محصولات.
- مشترک: ماژول های مشترک ، مانند مؤلفه های UI ، برنامه های کاربردی و یاران API.
کارخانه پرس و جو و FSD
حال بیایید با استفاده از معماری پروژه نگاه کنیم query factory
و FSD
رویکرد
ساختار پروژه:
src/
├── app/ // Global configurations, routing, and providers
├── entities/ // Entities
│ └── pokemon/
│ ├── api/
│ ├── model/
│ └── ui/
├── features/ // Features
├── widgets/ // Widgets
├── pages/ // Pages (PokemonsPage for example)
└── shared/ // Common modules, such as UI components, utilities..
مشترک (منابع مشترک)
مشترک شامل مؤلفه های مشترک ، برنامه های کاربردی ، تنظیمات و یاران API عمومی است. بیایید بنویسیم createQueries
عملکرد ، که به عنوان یک کارخانه پرس و جو خدمت می کند. بیایید فرض کنیم که ما از یک API ساده Crud برای برقراری ارتباط با سرور استفاده می کنیم:
import { keepPreviousData, queryOptions } from '@tanstack/react-query';
import * as qs from 'qs';
import { createQueryFn } from '../../api/createQueryFn';
import { createMutationFn } from '../../api/createMutationFn';
import { createDeleteMutationFn } from '../../api/createDeleteMutationFn';
import { createUpdateMutationFn } from '../../api/createUpdateMutationFn';
// We pass generics so that when we write code later, the types are displayed correctly.
export const createQueries = <
CreateResponse,
CreateBody,
ReadResponse,
ReadOneResponse,
UpdateResponse,
UpdateBody,
DeleteResponse,
DeleteParams
>(
entity: string
) => ({
all: () =>
queryOptions({
queryKey: [entity],
}),
create: () => ({
mutationKey: [entity],
mutationFn: (body: CreateBody) =>
createMutationFn<CreateResponse, CreateBody>({
path: `/${entity}`,
body,
}),
placeholderData: keepPreviousData,
}),
read: (filters) =>
queryOptions({
queryKey: [entity, filters],
queryFn: () =>
createQueryFn<ReadResponse>({
path: `/${entity}?${qs.stringify(filters)}`,
}),
placeholderData: keepPreviousData,
}),
readOne: ({ id }) =>
queryOptions({
queryKey: [entity, id],
queryFn: () =>
createQueryFn<ReadOneResponse>({
path: `/${entity}/${id}`,
}),
placeholderData: keepPreviousData,
}),
update: () => ({
mutationKey: [entity],
mutationFn: ({ id, body }) =>
createUpdateMutationFn<UpdateResponse, UpdateBody>({
path: `/${entity}/${id}`,
body,
}),
placeholderData: keepPreviousData,
}),
delete: () => ({
mutationKey: [entity],
mutationFn: (params: DeleteParams) =>
createDeleteMutationFn<DeleteResponse>({
path: `/${entity}/${params.id}`,
}),
placeholderData: keepPreviousData,
}),
});
این عملکرد یک شی را با تنظیمات پرس و جو برای عملیات اساسی CRUD برمی گرداند.
بیایید یک فایل آزمایش ایجاد کنیم createQueries.test.ts
:
import { describe, it, expect, vi } from 'vitest';
import { createQueries } from './createQueries.ts';
import * as api from '../../api/createQueryFn';
import * as mutationApi from '../../api/createMutationFn';
vi.mock('../../api/createQueryFn', () => ({
createQueryFn: vi.fn(),
}));
vi.mock('../../api/createMutationFn', () => ({
createMutationFn: vi.fn(),
}));
vi.mock('../../api/createDeleteMutationFn', () => ({
createDeleteMutationFn: vi.fn(),
}));
vi.mock('../../api/createUpdateMutationFn', () => ({
createUpdateMutationFn: vi.fn(),
}));
describe('createQueries', () => {
const entity = 'user';
it('should return correct query options for "all"', () => {
const queries = createQueries(entity);
const result = queries.all();
expect(result.queryKey).toEqual([entity]);
});
it('should create mutation for "create"', () => {
const queries = createQueries(entity);
const body = { name: 'Alexander' };
queries.create().mutationFn(body);
expect(mutationApi.createMutationFn).toHaveBeenCalledWith({
path: `/${entity}`,
body,
});
});
it('should return correct query options for "read"', () => {
const queries = createQueries(entity);
const filters = { page: 1 };
queries.read(filters).queryFn();
expect(api.createQueryFn).toHaveBeenCalledWith({
path: `/${entity}?page=1`,
});
});
it('should return correct query options for "readOne"', () => {
const queries = createQueries(entity);
const id = 123;
queries.readOne({ id }).queryFn();
expect(api.createQueryFn).toHaveBeenCalledWith({
path: `/${entity}/${id}`,
});
});
it('should create mutation for "update"', () => {
const queries = createQueries(entity);
const id = 123;
const body = { name: 'Updated' };
queries.update().mutationFn({ id, body });
expect(mutationApi.createUpdateMutationFn).toHaveBeenCalledWith({
path: `/${entity}/${id}`,
body,
});
});
it('should create mutation for "delete"', () => {
const queries = createQueries(entity);
const params = { id: 123 };
queries.delete().mutationFn(params);
expect(mutationApi.createDeleteMutationFn).toHaveBeenCalledWith({
path: `/${entity}/${params.id}`,
});
});
});
اکنون عملکرد ما آزمایش شده است
موجودات
نهادها اشیاء اصلی دامنه هستند که برنامه با آن کار می کند ، به عنوان مثال ، User
یا Pokemon
بشر هر موجودیت ماژول خاص خود را دارد که شامل تعاریف نوع داده ، قلاب های Crud ، اجزای UI برای نمایش و احتمالاً آداپتورها برای تعامل با API است.
ساختار مثال Pokemon
موجودیت:
src/
└── entities/
└── pokemon/
├── api/
│ ├── pokemon.query.ts // Pokemon Queries
│ ├── usePokemon.tsx // Hook for getting one Pokemon
│ ├── usePokemonCreate.tsx // Hook for Pokemon creation
│ ├── usePokemonDelete.tsx // Hook for Pokemon deletion
│ ├── usePokemonList.tsx // Hook for getting Pokemon list
│ └── usePokemonUpdate.tsx // Hook for Pokemon update
└── model/
└── Pokemon.ts // Types for Pokemon entity
└── ui/
├── PokemonList.tsx // React component for Pokemon list
└── PokemonCard.tsx // React component for Pokemon card
- API/UsePokemon*.ts: اجرای قلاب Crud برای API Pokemon.
-
model/pokemon.ts: تعاریف نوع داده برای
Pokemon
موجودیت - ui/pokemonlist.tsx وت ui/pokemoncard.tsx: مؤلفه های UI برای موجودیت Pokemon (نمایش لیستی از Pokemon و یک Pokemon جداگانه).
نمونه pokemon.query.ts با استفاده از createQueries
:
import { createQueries } from '../../../shared/lib/createQueries/createQueries';
import {
CreatePokemonResponse,
CreatePokemonBody,
ReadPokemonResponse,
ReadOnePokemonResponse,
UpdatePokemonResponse,
UpdatePokemonBody,
DeletePokemonResponse,
DeletePokemonParams,
} from '../model/Pokemon';
export const pokemonQueries = createQueries<
CreatePokemonResponse,
CreatePokemonBody,
ReadPokemonResponse,
ReadOnePokemonResponse,
UpdatePokemonResponse,
UpdatePokemonBody,
DeletePokemonResponse,
DeletePokemonParams
>('pokemon');
در createQueries
، انواع مورد نیاز برای تایپ مناسب و نام نهاد را با توجه به قرارداد پس زمینه منتقل می کنیم. سپس استفاده می کنیم pokemonQueries
برای ایجاد لازم CRUD
قلاب ، همانطور که با usePokemonList
:
import { useQuery } from '@tanstack/react-query';
import { pokemonQueries } from './pokemon.query';
type Props = {
limit: number;
offset: number;
};
export const usePokemonList = ({ limit, offset }: Props) => {
return useQuery({
...pokemonQueries.read({ limit, offset }),
});
};
ما همه را بدست می آوریم CRUD
قلاب های مورد نیاز برای برنامه ، که می تواند در اجزای UI یا سایر لایه های برنامه استفاده شود. این باعث می شود ساختار کد بیشتر محصور و سازگار شود FSD
بشر
بسته به توافق های موجود در پروژه خود ، می توانید یک کارخانه برای قلاب های Crud بنویسید ، یا فقط به صورت دستی فقط موارد مورد نیاز خود را ایجاد کنید ، همانطور که ما انجام دادیم.
ویژگی
ویژگی ها نشان دهنده اقدامات خاص کاربر است که ارزش کسب و کار را ارائه می دهد. به عنوان مثال ، ویرایش یا ایجاد یک Pokemon جدید. این ویژگی ها می توانند از موجودات استفاده کنند و در صورت لزوم آنها را در قوانین تجاری اضافی بپیچانند.
ساختار مثال create-pokemon
ویژگی:
src/
└── features/
└── create-pokemon/
├── model/
└── ui/
-
مدل/: ممکن است حاوی قلاب یا عملکردی برای ایجاد Pokemon باشد (به عنوان مثال ، استفاده
usePokemonCreate
ازentities/pokemon/api
). - UI/: مؤلفه هایی که فرم Add Pokemon یا UI را برای تأیید علاوه بر این ارائه می دهند.
import { usePokemonCreate } from
'../../../entities/pokemon/api/usePokemonCreate';
import { CreatePokemonBody } from '../../../entities/pokemon/model/Pokemon';
type Props = {
pokemon: CreatePokemonBody;
};
export const CreatePokemon = ({ pokemon }: Props) => {
const { mutate: createPokemon } = usePokemonCreate();
const handleCreate = () => {
createPokemon({
name: pokemon.name,
});
};
return (
<button
onClick={handleCreate}
className="bg-green-500 text-white p-2 rounded hover:bg-green-600 transition-colors"
>
Create {pokemon.name}
</button>
);
};
با استفاده از مؤلفه:
<CreatePokemon pokemon={{ name: 'Pikachu' }} />
ویراچه
ویجت ها ماژول های UI بزرگتر هستند که می توانند از چندین ویژگی و موجودات تشکیل شوند. به عنوان مثال ، الف PokemonProfile
ویجت ممکن است شامل لیستی از تمام سریال ها و بازی هایی باشد که Pokemon در آن ظاهر شده است ، اطلاعات مربوط به مشخصات آن و غیره.
می توانید نمونه مفصلی از این رویکرد را در پروژه نسخه ی نمایشی پیدا کنید.
نتیجه گیری
ما یک انعطاف پذیر و قابل استفاده مجدد را اجرا کرده ایم CRUD
سیستم قلاب با استفاده از @tanstack/react-query
وت axios
بشر اکنون می توانید به راحتی از این قلاب ها برای هر موجود در API خود استفاده کنید ، کد خود را به طور قابل توجهی ساده کرده و خوانایی را بهبود بخشید.
این روش به مقیاس بندی برنامه به راحتی و به حداقل رساندن کپی کردن کد کمک می کند. متقاضی FSD
اصول به ساختار پروژه کمک می کند و آن را مقیاس پذیر تر و حفظ می کند. ترکیب این رویکردها به شما امکان می دهد تا برنامه های انعطاف پذیر ایجاد کنید که در آن مدولار بودن و استقلال مؤلفه ، پروژه را برای پشتیبانی و گسترش آسان می کند.
سعی کنید این رویکرد را در پروژه خود بگنجانید ، و به سرعت متوجه خواهید شد که چگونه مدیریت وضعیت درخواست را ساده می کند و آن را در مؤلفه های React ادغام می کند.
پیوندهای جالب: