Project Kanban

Налаштування та Типізація

Почнемо з фундаменту. Нам потрібно встановити залежності та налаштувати TypeScript типи, щоб наш IntelliSense працював на повну.

Налаштування та Типізація

Почнемо з фундаменту. Нам потрібно встановити залежності та налаштувати TypeScript типи, щоб наш IntelliSense працював на повну.

Встановлення залежностей

npm install @reduxjs/toolkit react-redux react-beautiful-dnd axios
npm install --save-dev @types/react-beautiful-dnd
Якщо ви використовуєте React 18 Strict Mode, react-beautiful-dnd може мати проблеми з анімацією. Ми використаємо форк @hello-pangea/dnd або вимкнемо Strict Mode для drag-and-drop сторінок. Для цього туторіалу припустимо, що ми використовуємо @hello-pangea/dnd як сучасну заміну.
npm uninstall react-beautiful-dnd
npm install @hello-pangea/dnd

Типи даних (Types)

Створимо файл types/kanban.ts. Це наш контракт даних.

src/types/kanban.ts
export interface Task {
  id: string;
  content: string;
  createdAt: string;
}

export interface Column {
  id: string;
  title: string;
  taskIds: string[]; // Масив ID завдань в цій колонці (для порядку)
}

export interface BoardData {
  tasks: Record<string, Task>;
  columns: Record<string, Column>;
  columnOrder: string[]; // Масив ID колонок (для порядку)
}

// Тип для статусу завантаження
export type LoadingState = 'idle' | 'loading' | 'succeeded' | 'failed';

Типізація Store (Hooks)

У TypeScript ми не повинні використовувати стандартні useDispatch та useSelector, тому що вони не знають про структуру нашого стору. Ми створимо типізовані обгортки.

Створимо файл src/app/hooks.ts.

src/app/hooks.ts
import { TypedUseSelectorHook, useDispatch, useSelector } from 'react-redux';
import type { RootState, AppDispatch } from './store';

// Використовуйте ці хуки замість звичайних useDispatch і useSelector
export const useAppDispatch = () => useDispatch<AppDispatch>();
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector;

Налаштування Store

Створимо порожній стор, який ми будемо наповнювати.

src/app/store.ts
import { configureStore } from '@reduxjs/toolkit';

export const store = configureStore({
  reducer: {
    // Тут будуть наші редюсери
  },
});

// Виводимо типи з самого стору
export type RootState = ReturnType<typeof store.getState>;
export type AppDispatch = typeof store.dispatch;

Провайдер

Не забудьте обгорнути додаток у Provider в index.tsx (або main.tsx).

src/main.tsx
import React from 'react';
import ReactDOM from 'react-dom/client';
import { Provider } from 'react-redux';
import { store } from './app/store';
import App from './App';
import './index.css';

ReactDOM.createRoot(document.getElementById('root')!).render(
  // <React.StrictMode> // Можливо доведеться тимчасово вимкнути для DnD
    <Provider store={store}>
      <App />
    </Provider>
  // </React.StrictMode>
);

Тепер, коли у нас є типи та налаштований стор, ми можемо переходити до найцікавішого — створення слайсів. Почнемо з "серця" нашого додатку — boardSlice.

👉 Далі: Створення Board Slice та Normalization

Copyright © 2026