283 lines
7.8 KiB
TypeScript
283 lines
7.8 KiB
TypeScript
|
|
/**
|
|||
|
|
* Примеры использования сгенерированных use* функций
|
|||
|
|
* с SWR и React Query
|
|||
|
|
*/
|
|||
|
|
|
|||
|
|
import { Api, HttpClient } from './output/Api';
|
|||
|
|
import useSWR from 'swr';
|
|||
|
|
import { useQuery } from '@tanstack/react-query';
|
|||
|
|
|
|||
|
|
// ============================================
|
|||
|
|
// НАСТРОЙКА API КЛИЕНТА
|
|||
|
|
// ============================================
|
|||
|
|
|
|||
|
|
const httpClient = new HttpClient({
|
|||
|
|
baseUrl: 'https://cdn.example.com',
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
// Устанавливаем токен (например, из localStorage)
|
|||
|
|
if (typeof window !== 'undefined') {
|
|||
|
|
const token = localStorage.getItem('auth_token');
|
|||
|
|
if (token) {
|
|||
|
|
httpClient.setSecurityData({ token });
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const api = new Api(httpClient);
|
|||
|
|
|
|||
|
|
// ============================================
|
|||
|
|
// ПРИМЕР 1: ИСПОЛЬЗОВАНИЕ С SWR
|
|||
|
|
// ============================================
|
|||
|
|
|
|||
|
|
// Простой GET запрос без параметров
|
|||
|
|
function UserProfile() {
|
|||
|
|
const profileConfig = api.auth.useGetProfile();
|
|||
|
|
|
|||
|
|
const { data, error, isLoading } = useSWR(
|
|||
|
|
profileConfig.path, // Ключ для кеша
|
|||
|
|
() => api.auth.getProfile() // Функция для загрузки данных
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
if (isLoading) return <div>Загрузка...</div>;
|
|||
|
|
if (error) return <div>Ошибка: {error.message}</div>;
|
|||
|
|
if (!data) return null;
|
|||
|
|
|
|||
|
|
return (
|
|||
|
|
<div>
|
|||
|
|
<h1>Профиль пользователя</h1>
|
|||
|
|
<p>Email: {data.email}</p>
|
|||
|
|
<p>Имя: {data.firstName} {data.lastName}</p>
|
|||
|
|
<p>Email подтверждён: {data.isEmailVerified ? 'Да' : 'Нет'}</p>
|
|||
|
|
</div>
|
|||
|
|
);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// GET запрос с параметрами
|
|||
|
|
function ProjectDetails({ projectId }: { projectId: string }) {
|
|||
|
|
const projectConfig = api.projects.useFindOne({ id: projectId });
|
|||
|
|
|
|||
|
|
const { data: project, error, isLoading } = useSWR(
|
|||
|
|
[projectConfig.path, projectId], // Составной ключ
|
|||
|
|
() => api.projects.findOne({ id: projectId })
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
if (isLoading) return <div>Загрузка проекта...</div>;
|
|||
|
|
if (error) return <div>Ошибка: {error.message}</div>;
|
|||
|
|
if (!project) return null;
|
|||
|
|
|
|||
|
|
return (
|
|||
|
|
<div>
|
|||
|
|
<h2>{project.name}</h2>
|
|||
|
|
<p>{project.description}</p>
|
|||
|
|
<p>Bucket: {project.s3Bucket}</p>
|
|||
|
|
<p>Region: {project.s3Region}</p>
|
|||
|
|
</div>
|
|||
|
|
);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// Список с автоматической ревалидацией
|
|||
|
|
function ProjectsList() {
|
|||
|
|
const projectsConfig = api.projects.useFindAll();
|
|||
|
|
|
|||
|
|
const { data: projects, error, isLoading, mutate } = useSWR(
|
|||
|
|
projectsConfig.path,
|
|||
|
|
() => api.projects.findAll(),
|
|||
|
|
{
|
|||
|
|
refreshInterval: 5000, // Обновлять каждые 5 секунд
|
|||
|
|
revalidateOnFocus: true, // Обновлять при фокусе на окно
|
|||
|
|
}
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
const handleCreateProject = async () => {
|
|||
|
|
await api.projects.create({
|
|||
|
|
name: 'Новый проект',
|
|||
|
|
description: 'Описание',
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
// Обновляем список
|
|||
|
|
mutate();
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
if (isLoading) return <div>Загрузка списка...</div>;
|
|||
|
|
if (error) return <div>Ошибка: {error.message}</div>;
|
|||
|
|
|
|||
|
|
return (
|
|||
|
|
<div>
|
|||
|
|
<h2>Мои проекты ({projects?.length || 0})</h2>
|
|||
|
|
<button onClick={handleCreateProject}>Создать проект</button>
|
|||
|
|
<ul>
|
|||
|
|
{projects?.map((project) => (
|
|||
|
|
<li key={project.id}>
|
|||
|
|
{project.name} - {project.slug}
|
|||
|
|
</li>
|
|||
|
|
))}
|
|||
|
|
</ul>
|
|||
|
|
</div>
|
|||
|
|
);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// ============================================
|
|||
|
|
// ПРИМЕР 2: ИСПОЛЬЗОВАНИЕ С REACT QUERY
|
|||
|
|
// ============================================
|
|||
|
|
|
|||
|
|
function UserProfileWithReactQuery() {
|
|||
|
|
const profileConfig = api.auth.useGetProfile();
|
|||
|
|
|
|||
|
|
const { data, error, isLoading } = useQuery({
|
|||
|
|
queryKey: [profileConfig.path],
|
|||
|
|
queryFn: () => api.auth.getProfile(),
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
if (isLoading) return <div>Загрузка...</div>;
|
|||
|
|
if (error) return <div>Ошибка</div>;
|
|||
|
|
|
|||
|
|
return (
|
|||
|
|
<div>
|
|||
|
|
<h1>{data?.firstName} {data?.lastName}</h1>
|
|||
|
|
<p>{data?.email}</p>
|
|||
|
|
</div>
|
|||
|
|
);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function ProjectsListWithReactQuery() {
|
|||
|
|
const projectsConfig = api.projects.useFindAll();
|
|||
|
|
|
|||
|
|
const { data: projects, isLoading } = useQuery({
|
|||
|
|
queryKey: [projectsConfig.path],
|
|||
|
|
queryFn: () => api.projects.findAll(),
|
|||
|
|
staleTime: 5 * 60 * 1000, // 5 минут
|
|||
|
|
refetchInterval: 30000, // Обновлять каждые 30 секунд
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
if (isLoading) return <div>Загрузка...</div>;
|
|||
|
|
|
|||
|
|
return (
|
|||
|
|
<div>
|
|||
|
|
<h2>Проекты</h2>
|
|||
|
|
{projects?.map((p) => (
|
|||
|
|
<div key={p.id}>{p.name}</div>
|
|||
|
|
))}
|
|||
|
|
</div>
|
|||
|
|
);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// ============================================
|
|||
|
|
// ПРИМЕР 3: УСЛОВНАЯ ЗАГРУЗКА
|
|||
|
|
// ============================================
|
|||
|
|
|
|||
|
|
function ConditionalProfile({ userId }: { userId?: string }) {
|
|||
|
|
const profileConfig = api.auth.useGetProfile();
|
|||
|
|
|
|||
|
|
const { data } = useSWR(
|
|||
|
|
// Загружаем только если есть userId
|
|||
|
|
userId ? profileConfig.path : null,
|
|||
|
|
() => api.auth.getProfile()
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
return data ? <div>{data.email}</div> : null;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// ============================================
|
|||
|
|
// ПРИМЕР 4: ЗАВИСИМЫЕ ЗАПРОСЫ
|
|||
|
|
// ============================================
|
|||
|
|
|
|||
|
|
function DependentQueries() {
|
|||
|
|
// Сначала получаем список проектов
|
|||
|
|
const projectsConfig = api.projects.useFindAll();
|
|||
|
|
const { data: projects } = useSWR(
|
|||
|
|
projectsConfig.path,
|
|||
|
|
() => api.projects.findAll()
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
// Затем получаем первый проект (только когда список загружен)
|
|||
|
|
const firstProjectId = projects?.[0]?.id;
|
|||
|
|
const projectConfig = firstProjectId
|
|||
|
|
? api.projects.useFindOne({ id: firstProjectId })
|
|||
|
|
: null;
|
|||
|
|
|
|||
|
|
const { data: firstProject } = useSWR(
|
|||
|
|
projectConfig ? [projectConfig.path, firstProjectId] : null,
|
|||
|
|
() => firstProjectId ? api.projects.findOne({ id: firstProjectId }) : null
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
return (
|
|||
|
|
<div>
|
|||
|
|
<h3>Всего проектов: {projects?.length || 0}</h3>
|
|||
|
|
{firstProject && (
|
|||
|
|
<div>
|
|||
|
|
<h4>Первый проект:</h4>
|
|||
|
|
<p>{firstProject.name}</p>
|
|||
|
|
</div>
|
|||
|
|
)}
|
|||
|
|
</div>
|
|||
|
|
);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// ============================================
|
|||
|
|
// ПРИМЕР 5: СОЗДАНИЕ ХУКА-ОБЁРТКИ
|
|||
|
|
// ============================================
|
|||
|
|
|
|||
|
|
// Универсальный хук для всех GET запросов
|
|||
|
|
function useApiQuery<T>(
|
|||
|
|
useConfigFn: () => { path: string; method: 'GET'; secure?: boolean },
|
|||
|
|
apiFn: () => Promise<T>,
|
|||
|
|
options?: Parameters<typeof useSWR>[2]
|
|||
|
|
) {
|
|||
|
|
const config = useConfigFn();
|
|||
|
|
return useSWR<T>(config.path, apiFn, options);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// Использование
|
|||
|
|
function MyComponent() {
|
|||
|
|
const { data, error, isLoading } = useApiQuery(
|
|||
|
|
api.auth.useGetProfile,
|
|||
|
|
api.auth.getProfile,
|
|||
|
|
{ revalidateOnFocus: true }
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
// ...
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// ============================================
|
|||
|
|
// ПРИМЕР 6: ПОЛЬЗОВАТЕЛЬСКИЙ FETCHER ДЛЯ SWR
|
|||
|
|
// ============================================
|
|||
|
|
|
|||
|
|
// Создаём универсальный fetcher
|
|||
|
|
const apiFetcher = async (key: string | string[]) => {
|
|||
|
|
const path = Array.isArray(key) ? key[0] : key;
|
|||
|
|
|
|||
|
|
// Находим соответствующий метод API
|
|||
|
|
// В реальном приложении можно использовать маппинг
|
|||
|
|
return api.auth.getProfile(); // пример
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
// SWRConfig для всего приложения
|
|||
|
|
import { SWRConfig } from 'swr';
|
|||
|
|
|
|||
|
|
function App() {
|
|||
|
|
return (
|
|||
|
|
<SWRConfig
|
|||
|
|
value={{
|
|||
|
|
fetcher: apiFetcher,
|
|||
|
|
revalidateOnFocus: false,
|
|||
|
|
dedupingInterval: 2000,
|
|||
|
|
}}
|
|||
|
|
>
|
|||
|
|
<UserProfile />
|
|||
|
|
<ProjectsList />
|
|||
|
|
</SWRConfig>
|
|||
|
|
);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
export {
|
|||
|
|
UserProfile,
|
|||
|
|
ProjectDetails,
|
|||
|
|
ProjectsList,
|
|||
|
|
UserProfileWithReactQuery,
|
|||
|
|
ProjectsListWithReactQuery,
|
|||
|
|
ConditionalProfile,
|
|||
|
|
DependentQueries,
|
|||
|
|
useApiQuery,
|
|||
|
|
};
|
|||
|
|
|