← Назад к вопросам
В каком случае данные кладутся в store
2.0 Middle🔥 171 комментариев
#State Management
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI2 апр. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
В каком случае данные кладутся в store
Store (хранилище состояния) используется для централизованного управления глобальным состоянием приложения. Решение о том, класть ли данные в store, должно приниматься на основе критериев сложности и масштаба приложения.
Когда НУЖНО использовать store
1. Данные нужны многим компонентам в разных частях приложения
Если состояние требуется компонентам, находящимся на разных уровнях иерархии, и нет общего родителя:
// Redux/Zustand
const userStore = create(set => ({
user: null,
isAuthenticated: false,
login: async (credentials) => {
const response = await fetch("/api/login", {
method: "POST",
body: JSON.stringify(credentials)
});
const user = await response.json();
set({ user, isAuthenticated: true });
},
logout: () => set({ user: null, isAuthenticated: false })
}));
// Компонент Header может использовать
function Header() {
const { user, logout } = userStore();
return user ? <button onClick={logout}>{user.name}</button> : null;
}
// Компонент Profile на другой странице тоже
function Profile() {
const { user } = userStore();
return <div>{user.bio}</div>;
}
2. Состояние часто изменяется и влияет на много компонентов
Prop drilling (передача пропсов через множество компонентов) становится неудобным:
// ❌ Плохо — много передачи пропсов
function App() {
const [user, setUser] = useState(null);
const [theme, setTheme] = useState("light");
const [notifications, setNotifications] = useState([]);
return (
<Layout user={user} theme={theme} notifications={notifications}>
<Sidebar user={user} theme={theme} />
<Main user={user} theme={theme} onNotify={setNotifications} />
</Layout>
);
}
// ✅ Хорошо — используем store
const appStore = create(set => ({
user: null,
theme: "light",
notifications: [],
setUser: (user) => set({ user }),
setTheme: (theme) => set({ theme }),
addNotification: (notif) => set(state => ({
notifications: [...state.notifications, notif]
}))
}));
function App() {
return (
<Layout>
<Sidebar />
<Main />
</Layout>
);
}
3. Синхронизация состояния между вкладками/окнами
Данные нужно синхронизировать в реальном времени:
const cartStore = create(
persist(
set => ({
items: [],
addItem: (item) => set(state => ({
items: [...state.items, item]
})),
clear: () => set({ items: [] })
}),
{
name: "cart-storage", // ключ в localStorage
storage: localStorage
}
)
);
4. Сложная бизнес-логика с множеством экшенов
Если состояние имеет сложные зависимости и много операций:
const ordersStore = create(set => ({
orders: [],
filters: { status: "all", dateRange: null },
sortBy: "date",
// Сложная логика фильтрации и сортировки
getFilteredOrders: (state) => {
let filtered = state.orders;
if (state.filters.status !== "all") {
filtered = filtered.filter(o => o.status === state.filters.status);
}
if (state.sortBy === "date") {
filtered.sort((a, b) => b.date - a.date);
}
return filtered;
},
setFilter: (filters) => set({ filters }),
setSortBy: (sortBy) => set({ sortBy }),
addOrder: (order) => set(state => ({
orders: [...state.orders, order]
}))
}));
Когда НЕ нужно использовать store
1. Локальное состояние UI компонента
// ✅ useState достаточно
function Modal() {
const [isOpen, setIsOpen] = useState(false);
const [formData, setFormData] = useState("");
return (
<>
<button onClick={() => setIsOpen(true)}>Открыть</button>
{isOpen && <div>{formData}</div>}
</>
);
}
2. Состояние нужно только компонентам с общим родителем
// ✅ Поднять в родителя
function Parent() {
const [count, setCount] = useState(0);
return (
<>
<Child1 count={count} />
<Child2 count={count} onIncrement={() => setCount(count + 1)} />
</>
);
}
3. Состояние URL (фильтры, поиск, пагинация)
// ✅ URL параметры
function ProductsList() {
const router = useRouter();
const category = router.query.category || "all";
const page = router.query.page || "1";
const handleFilter = (cat) => {
router.push({ query: { category: cat, page: "1" } });
};
return <div>{/* товары */}</div>;
}
Критерии для выбора хранилища
| Ситуация | Решение |
|---|---|
| 1-2 компонента, близкие друг к другу | useState в компоненте |
| Компоненты-сёстры | Поднять в общего родителя |
| Много компонентов в разных местах | Context API или простой store (Zustand) |
| Очень большое приложение, сложная логика | Redux или MobX |
| Данные нужны сразу при загрузке | Инициализировать в store при старте |
| Фильтры, поиск, сортировка | URL параметры |
Лучшие практики
1. Разделяй по доменам
// store/auth.js
export const useAuthStore = create(set => ({
user: null,
login: async (credentials) => { /* ... */ }
}));
// store/products.js
export const useProductsStore = create(set => ({
items: [],
filters: {},
fetchProducts: async () => { /* ... */ }
}));
// Использование
function App() {
const user = useAuthStore(state => state.user);
const items = useProductsStore(state => state.items);
}
2. Не кладь ВСЁ в store
// ❌ Плохо — store перегружен
const megaStore = create(set => ({
user: null,
products: [],
cart: [],
wishlist: [],
notifications: [],
isMenuOpen: false, // этого не нужно в store!
formInputValue: "", // этого тоже!
// ...
}));
// ✅ Хорошо — разделение ответственности
const useAuthStore = create(set => ({ user: null }));
const useProductsStore = create(set => ({ products: [] }));
const useCartStore = create(set => ({ items: [] }));
3. Нормализуй структуру
// ❌ Денормализованно — дублирование
const orders = [
{ id: 1, userId: 10, user: { id: 10, name: "John" } },
{ id: 2, userId: 10, user: { id: 10, name: "John" } }
];
// ✅ Нормализованно
const orders = {
byId: {
1: { id: 1, userId: 10 },
2: { id: 2, userId: 10 }
},
allIds: [1, 2]
};
const users = {
byId: {
10: { id: 10, name: "John" }
}
};
Ключевые выводы
- Store нужен когда состояние используется много компонентами в разных частях приложения
- Не кладь всё подряд — разделяй по доменам и по типам (глобальное vs локальное)
- Начни простым — useState → Context → Store
- URL параметры для фильтров и навигации
- localStorage для сохранения между сеансами