Zustand и Ant Design

Zustand — это лёгкая и простая в использовании библиотека для управления состоянием в приложениях на React. Она идеально подходит для проектов, где требуется минимальный boilerplate, высокая производительность и удобный синтаксис. В сочетании с Ant Design (AntD) Zustand позволяет создавать сложные интерфейсы с чистой архитектурой и отзывчивым состоянием компонентов.


Основы Zustand

Создание состояния в Zustand происходит через функцию create, которая возвращает хук для использования состояния в компонентах:

import create from 'zustand';

const useStore = create((set) => ({
  count: 0,
  increment: () => set((state) => ({ count: state.count + 1 })),
  decrement: () => set((state) => ({ count: state.count - 1 })),
}));
  • count — это поле состояния.
  • increment и decrement — функции для изменения состояния.
  • set используется для обновления состояния. Оно может принимать функцию с предыдущим состоянием.

Использование хука в компоненте:

import React from 'react';
import { Button } from 'antd';

function Counter() {
  const { count, increment, decrement } = useStore();
  
  return (
    <div>
      <h2>Счётчик: {count}</h2>
      <Button onCl ick={increment} type="primary">Увеличить</Button>
      <Button onCl ick={decrement} style={{ marginLeft: 8 }}>Уменьшить</Button>
    </div>
  );
}

Интеграция с Ant Design Components

Ant Design предоставляет широкий набор UI-компонентов, которые можно легко связать с состоянием Zustand. Основные паттерны:

Формы (Form)

Формы в AntD можно интегрировать с Zustand для хранения данных:

import { Form, Input, Button } from 'antd';

const useFormStore = create((set) => ({
  username: '',
  setUsername: (value) => set({ username: value }),
}));

function UserForm() {
  const { username, setUsername } = useFormStore();
  
  return (
    <Form layout="vertical">
      <Form.Item label="Имя пользователя">
        <Input value={username} onCha nge={(e) => setUsername(e.target.value)} />
      </Form.Item>
      <Form.Item>
        <Button type="primary" onCl ick={() => console.log(username)}>Отправить</Button>
      </Form.Item>
    </Form>
  );
}

Ключевые моменты:

  • value и onChange связывают поле формы с состоянием.
  • Любые изменения в состоянии мгновенно отражаются в UI без дополнительных хуков.

Таблицы (Table)

Zustand удобно использовать для хранения данных таблицы и управления сортировкой, фильтрацией и пагинацией:

import { Table } from 'antd';

const useTableStore = create((set) => ({
  data: [
    { key: 1, name: 'Иван', age: 28 },
    { key: 2, name: 'Мария', age: 32 },
  ],
  addRow: (row) => set((state) => ({ data: [...state.data, row] })),
}));

function UserTable() {
  const { data, addRow } = useTableStore();

  const columns = [
    { title: 'Имя', dataIndex: 'name', key: 'name' },
    { title: 'Возраст', dataIndex: 'age', key: 'age' },
  ];

  return <Table columns={columns} dataSource={data} />;
}

Преимущества:

  • Все изменения данных таблицы управляются через Zustand.
  • Легко расширять функциональность: фильтры, сортировка, пагинация.

Модальные окна (Modal)

AntD Modal часто требует управления видимостью. Zustand идеально справляется с этим:

import { Modal, Button } from 'antd';

const useModalStore = create((set) => ({
  isVisible: false,
  open: () => set({ isVisible: true }),
  close: () => set({ isVisible: false }),
}));

function DemoModal() {
  const { isVisible, open, close } = useModalStore();

  return (
    <>
      <Button type="primary" onCl ick={open}>Показать модальное окно</Button>
      <Modal visible={isVisible} onCan cel={close} onOk={close}>
        <p>Содержимое модального окна</p>
      </Modal>
    </>
  );
}

Особенности:

  • Управление открытием/закрытием через состояние.
  • Можно легко объединять несколько модальных окон в одном хранилище Zustand.

Паттерны масштабирования

Множественные состояния

Для сложных интерфейсов рекомендуется создавать отдельные стора для разных доменов:

const useUserStore = create((set) => ({
  users: [],
  addUser: (user) => set((state) => ({ users: [...state.users, user] })),
}));

const useUIStore = create((set) => ({
  modalVisible: false,
  toggleModal: () => set((state) => ({ modalVisible: !state.modalVisible })),
}));

Селекторы и мемоизация

Zustand поддерживает селекторы для оптимизации перерисовок:

const userCount = useUserStore((state) => state.users.length);

Только компоненты, использующие userCount, будут перерисованы при изменении длины массива, а не при каждом обновлении других полей состояния.

Middleware для логирования и персистентности

import { persist, devtools } from 'zustand/middleware';

const usePersistentStore = create(
  devtools(
    persist(
      (set) => ({
        theme: 'light',
        toggleTheme: () => set((state) => ({ theme: state.theme === 'light' ? 'dark' : 'light' })),
      }),
      { name: 'theme-storage' }
    )
  )
);
  • devtools помогает отслеживать изменения состояния в браузере.
  • persist сохраняет состояние в localStorage или sessionStorage.

Рекомендации по совместному использованию с Ant Design

  • Локальное состояние компонентов: Для мелких интерактивных элементов лучше использовать локальный useState, чтобы не перегружать глобальный стор.
  • Глобальное состояние: Таблицы, формы и модальные окна, которые используются в разных местах приложения, лучше хранить в Zustand.
  • Комбинирование хуков: Можно использовать несколько стора одновременно для одного компонента, комбинируя useStoreA и useStoreB.
  • Оптимизация производительности: Использовать селекторы и избегать подписки на весь объект состояния, чтобы уменьшить ненужные перерисовки.

Интеграция Zustand с Ant Design обеспечивает чистое, масштабируемое и отзывчивое управление состоянием. Она минимизирует boilerplate, упрощает поддержку кода и делает разработку интерфейсов более структурированной и предсказуемой.