Перейти к основному содержимому

State Management

Приложение использует два типа state management:

ТипИнструментНазначение
Server StateTanStack QueryДанные с сервера (курсы, уроки, прогресс)
Client StateZustandUI состояние (тема, язык, игры)

Zustand Stores

Все stores находятся в src/stores/:

Persist Stores (сохраняются в AsyncStorage)

// src/stores/settings.ts
import { create } from 'zustand';
import { persist, createJSONStorage } from 'zustand/middleware';
import AsyncStorage from '@react-native-async-storage/async-storage';

interface SettingsState {
theme: 'light' | 'dark' | 'system';
language: 'en' | 'ru' | 'uk';
notificationsEnabled: boolean;
setTheme: (theme: SettingsState['theme']) => void;
setLanguage: (language: SettingsState['language']) => void;
}

export const useSettingsStore = create<SettingsState>()(
persist(
(set) => ({
theme: 'system',
language: 'en',
notificationsEnabled: true,
setTheme: (theme) => set({ theme }),
setLanguage: (language) => set({ language }),
}),
{
name: 'settings-storage',
storage: createJSONStorage(() => AsyncStorage),
}
)
);

Ephemeral Stores (только в памяти)

// src/stores/memory-cards-store.ts
import { create } from 'zustand';

interface MemoryCardsState {
cards: Card[];
flippedIndices: number[];
matchedPairs: number[];
moves: number;
flipCard: (index: number) => void;
reset: () => void;
}

export const useMemoryCardsStore = create<MemoryCardsState>((set) => ({
cards: [],
flippedIndices: [],
matchedPairs: [],
moves: 0,
flipCard: (index) => set((state) => ({
flippedIndices: [...state.flippedIndices, index],
moves: state.moves + 1,
})),
reset: () => set({
cards: [],
flippedIndices: [],
matchedPairs: [],
moves: 0,
}),
}));

Список stores

StorePersistНазначение
settings.tsТема, язык, уведомления
chat-store.tsСообщения AI чата
lesson-viewer-store.tsСкролл, активная вкладка
lesson-progress-store.tsВременный прогресс урока
mindmap-store.tsPan/zoom состояние
memory-cards-store.tsСостояние игры Memory
pattern-sequence-store.tsСостояние игры Pattern
learning-style-store.tsVARK quiz состояние
course-creation-store.tsWizard создания курса

Паттерны использования

Селекторы (для оптимизации ререндеров)

// ❌ Плохо — компонент ререндерится при любом изменении store
const store = useSettingsStore();

// ✅ Хорошо — только при изменении theme
const theme = useSettingsStore((state) => state.theme);

Actions внутри store

// Все actions определяются в store
export const useChatStore = create<ChatState>((set, get) => ({
messages: [],

addMessage: (message) => set((state) => ({
messages: [...state.messages, message],
})),

clearMessages: () => set({ messages: [] }),

// Доступ к текущему состоянию через get()
getLastMessage: () => {
const { messages } = get();
return messages[messages.length - 1];
},
}));

Подписка на изменения

// Подписка вне React компонента
const unsubscribe = useSettingsStore.subscribe(
(state) => state.theme,
(theme) => {
console.log('Theme changed:', theme);
}
);

TanStack Query для Server State

Server state управляется через TanStack Query. См. Data Fetching.