23. Реальный проект: Dashboard
Полный стек TanStack в одном приложении
Заголовок раздела «Полный стек TanStack в одном приложении»В этом финальном уроке объединим все изученные инструменты в работающий дашборд:
- TanStack Query — загрузка данных, кэширование, мутации
- TanStack Table — таблица с сортировкой, фильтрацией и пагинацией
- TanStack Router концепции — навигация между разделами
- TanStack Form концепции — форма редактирования с валидацией
Архитектура дашборда
Заголовок раздела «Архитектура дашборда»Dashboard├── QueryClientProvider (TanStack Query)├── Sidebar Navigation└── Main Content ├── Users Table │ ├── useQuery(['users']) — загрузка данных │ ├── useReactTable — сортировка, фильтрация, пагинация │ └── useMutation — удаление пользователя ├── User Detail Panel │ ├── useQuery(['user', id]) — детали пользователя │ └── Edit Form с валидацией └── Cache Status Panel └── Отображение состояния кэша QueryКлючевые паттерны
Заголовок раздела «Ключевые паттерны»1. Единый QueryClient на приложение
Заголовок раздела «1. Единый QueryClient на приложение»const queryClient = new QueryClient({ defaultOptions: { queries: { staleTime: 1000 * 60 * 2 } },})2. Инвалидация после мутаций
Заголовок раздела «2. Инвалидация после мутаций»const deleteUser = useMutation({ mutationFn: (id) => api.deleteUser(id), onSuccess: () => queryClient.invalidateQueries({ queryKey: ['users'] }),})3. Optimistic UI + Rollback
Заголовок раздела «3. Optimistic UI + Rollback»const updateUser = useMutation({ mutationFn: api.updateUser, onMutate: async (updatedUser) => { const prev = queryClient.getQueryData(['users']) queryClient.setQueryData(['users'], (old) => old.map(u => u.id === updatedUser.id ? updatedUser : u)) return { prev } }, onError: (_, __, ctx) => queryClient.setQueryData(['users'], ctx.prev), onSettled: () => queryClient.invalidateQueries({ queryKey: ['users'] }),})