Проєкт: Kanban Board (Trello Clone)
Проєкт: Kanban Board (Trello Clone)
Щоб закріпити знання Redux Toolkit та RTK Query, ми створимо повноцінний додаток — клон Trello. Це не просто "Todo list". Це складний додаток зі складною логікою переміщення карток, оптимістичними оновленнями та синхронізацією з сервером.
Технічний стек
Ми будемо використовувати сучасний набір інструментів:
- React 18: UI бібліотека.
- Redux Toolkit: Управління клієнтським станом (drag & drop, UI state).
- RTK Query: Управління серверним станом (caching, synchronization).
- React Beautiful DnD: Бібліотека для Drag-and-Drop.
- Tailwind CSS: Стилізація.
- Mock Service Worker (MSW) або MirageJS: Для емуляції бекенду.
Функціональні вимоги
- Колонки: Створення, видалення, перейменування, зміна порядку.
- Завдання (Tasks): Створення, редагування, видалення.
- Drag & Drop:
- Переміщення завдань всередині колонки.
- Переміщення завдань між колонками.
- Переміщення самих колонок.
- Асинхронність: Всі зміни мають зберігатися на сервері.
- Optimistic Updates: Інтерфейс має оновлюватися миттєво, не чекаючи відповіді сервера.
Проєктування Структури Даних
Це найважливіший етап. Якщо ми неправильно спроєктуємо структуру даних, нам буде дуже важко писати редюсери для Drag & Drop.
API Response Shape
Наш бекенд повертає дані в такому форматі:
{
"columns": [
{
"id": "column-1",
"title": "To Do",
"taskIds": ["task-1", "task-2"] // Порядок завдань важливий!
},
{
"id": "column-2",
"title": "In Progress",
"taskIds": []
}
],
"tasks": [
{ "id": "task-1", "content": "Налаштувати Redux" },
{ "id": "task-2", "content": "Створити слайси" }
],
"columnOrder": ["column-1", "column-2"] // Порядок колонок
}
Redux State Shape (Normalized)
Ми будемо використовувати нормалізовану структуру для максимальної продуктивності. Завдання не будуть жити всередині колонок. Вони будуть жити окремо.
interface RootState {
// Кеш RTK Query для серверних даних
api: ApiState
// Локальний UI стан (наприклад, яка модалка відкрита)
ui: UiState
// Дані дошки (ми дублюємо їх тут для миттєвого Drag&Drop)
board: {
tasks: {
ids: string[]
entities: Record<string, Task>
}
columns: {
ids: string[]
entities: Record<string, Column>
}
columnOrder: string[]
}
}
Чому ми дублюємо дані в board slice, якщо вони вже є в кеші RTK Query?
Drag & Drop вимагає миттєвих синхронних оновлень локального стану. Кеш RTK Query призначений для синхронізації з сервером, і маніпулювати ним вручну для складних dnd-операцій може бути незручно.
Ми використаємо гібридний підхід:
- RTK Query завантажує дані.
- Ми копіюємо їх в локальний slice
board. - Всі dnd-операції відбуваються в
board(миттєво). - У фоні ми відправляємо мутації через RTK Query для синхронізації з сервером.
Схема взаємодії
Це архітектура професійного рівня. Вона забезпечує ідеальну чутливість інтерфейсу (60 FPS) і надійність даних.
Архітектура та Best Practices
Тепер, коли ви знаєте всі інструменти Redux Toolkit, давайте поговоримо про те, як організувати код, щоб проєкт залишався підтримуваним навіть при зростанні.
Налаштування та Типізація
Почнемо з фундаменту. Нам потрібно встановити залежності та налаштувати TypeScript типи, щоб наш IntelliSense працював на повну.