← Назад к вопросам

В каком случае данные кладутся в 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 для сохранения между сеансами
В каком случае данные кладутся в store | PrepBro