Управление состоянием компонентов

Основы состояния в React и Ant Design

Компоненты Ant Design (antd) полностью совместимы с моделью управления состоянием React. Любой визуальный элемент, будь то форма, таблица или кнопка, может использовать внутреннее состояние компонента через useState, useReducer или внешние менеджеры состояния, такие как Redux или MobX.

Пример базового состояния кнопки:

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

const ToggleButton = () => {
  const [active, setActive] = useState(false);

  return (
    <Button type={active ? 'primary' : 'default'} onCl ick={() => setActive(!active)}>
      {active ? 'Активен' : 'Неактивен'}
    </Button>
  );
};

export default ToggleButton;

В этом примере свойство type кнопки динамически меняется в зависимости от состояния active, а обработчик onClick обновляет состояние.


Формы и управление их состоянием

Компонент Form Ant Design предоставляет собственный контроллер состояния через Form.useForm(). Это позволяет синхронизировать данные формы, валидировать их и управлять отправкой.

Пример использования Form.useForm:

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

const DemoForm = () => {
  const [form] = Form.useForm();

  const onFin ish = (values) => {
    console.log('Данные формы:', values);
  };

  const onRe set = () => {
    form.resetFields();
  };

  return (
    <Form form={form} onFin ish={onFinish} layout="vertical">
      <Form.Item
        name="username"
        label="Имя пользователя"
        rules={[{ required: true, message: 'Введите имя пользователя!' }]}
      >
        <Input />
      </Form.Item>
      <Form.Item
        name="email"
        label="Email"
        rules={[{ type: 'email', message: 'Введите корректный Email!' }]}
      >
        <Input />
      </Form.Item>
      <Form.Item>
        <Button type="primary" htmlType="submit">
          Отправить
        </Button>
        <Button htmlType="button" onCl ick={onReset} style={{ marginLeft: '8px' }}>
          Сброс
        </Button>
      </Form.Item>
    </Form>
  );
};

export default DemoForm;

Ключевой момент: form.resetFields() и form.setFieldsValue() позволяют полностью контролировать внутреннее состояние формы без прямого изменения useState.


Таблицы и состояние данных

Компонент Table тесно интегрируется с состоянием React для управления сортировкой, фильтрацией и пагинацией.

Пример управления таблицей с локальным состоянием:

import React, { useState } from 'react';
import { Table } from 'antd';

const DataTable = () => {
  const [data, setData] = useState([
    { key: 1, name: 'Иван', age: 25 },
    { key: 2, name: 'Мария', age: 30 },
    { key: 3, name: 'Петр', age: 28 },
  ]);

  const [pagination, setPagination] = useState({ current: 1, pageSize: 2 });

  const handleTableChange = (pag) => {
    setPagination(pag);
  };

  return (
    <Table
      columns={[
        { title: 'Имя', dataIndex: 'name', key: 'name' },
        { title: 'Возраст', dataIndex: 'age', key: 'age' },
      ]}
      dataSource={data}
      pagination={pagination}
      onCha nge={handleTableChange}
    />
  );
};

export default DataTable;

Здесь пагинация и любые изменения таблицы синхронизируются с состоянием React, что позволяет реализовать кастомное поведение фильтров или сортировки.


Модальные окна и видимость

Компоненты Modal и Drawer используют состояние для управления их видимостью. Основное свойство — visible или open в новых версиях.

Пример модального окна:

import React, { useState } from 'react';
import { Modal, Button } from 'antd';

const DemoModal = () => {
  const [isOpen, setIsOpen] = useState(false);

  return (
    <>
      <Button type="primary" onCl ick={() => setIsOpen(true)}>
        Открыть модальное окно
      </Button>
      <Modal
        title="Пример модального окна"
        open={isOpen}
        onOk={() => setIsOpen(false)}
        onCan cel={() => setIsOpen(false)}
      >
        <p>Содержимое модального окна.</p>
      </Modal>
    </>
  );
};

export default DemoModal;

Управление состоянием через useState позволяет легко контролировать появление и скрытие модальных компонентов без сложной логики.


Управление состоянием с Redux и Ant Design

Для крупных приложений локальное состояние компонентов может быть недостаточно. Ant Design полностью совместим с Redux:

import React from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { Button } from 'antd';
import { increment, decrement } from './counterSlice';

const Counter = () => {
  const count = useSelector((state) => state.counter.value);
  const dispatch = useDispatch();

  return (
    <>
      <p>Счётчик: {count}</p>
      <Button onCl ick={() => dispatch(increment())}>Увеличить</Button>
      <Button onCl ick={() => dispatch(decrement())} style={{ marginLeft: 8 }}>
        Уменьшить
      </Button>
    </>
  );
};

export default Counter;

Ключевой аспект: Ant Design компоненты реагируют на обновления состояния Redux точно так же, как на локальное состояние, что обеспечивает единообразие в управлении данными на уровне всего приложения.


Состояние загрузки и асинхронные операции

Для компонентов Button, Spin или Table состояние загрузки управляется через свойства loading. Это позволяет динамически отображать спиннеры и блокировать действия во время выполнения асинхронных операций.

import React, { useState } from 'react';
import { Button, Spin } from 'antd';

const LoadingDemo = () => {
  const [loading, setLoading] = useState(false);

  const fetchData = async () => {
    setLoading(true);
    await new Promise((resolve) => setTimeout(resolve, 2000));
    setLoading(false);
  };

  return (
    <>
      <Button type="primary" loading={loading} onCl ick={fetchData}>
        Загрузить данные
      </Button>
      {loading && <Spin style={{ marginLeft: '10px' }} />}
    </>
  );
};

export default LoadingDemo;

Использование свойства loading делает интерфейс отзывчивым и информативным для пользователя.


Управление сложными состояниями с useReducer

Для компонентов с множеством взаимозависимых состояний (Form с динамическими полями, таблицы с фильтрами, модальные окна с вложенными действиями) эффективнее применять useReducer:

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

const initialState = { count: 0, step: 1 };

function reducer(state, action) {
  switch (action.type) {
    case 'increment':
      return { ...state, count: state.count + state.step };
    case 'decrement':
      return { ...state, count: state.count - state.step };
    case 'setStep':
      return { ...state, step: action.payload };
    default:
      return state;
  }
}

const ReducerDemo = () => {
  const [state, dispatch] = useReducer(reducer, initialState);

  return (
    <>
      <p>Счётчик: {state.count}</p>
      <Button onCl ick={() => dispatch({ type: 'increment' })}>+</Button>
      <Button onCl ick={() => dispatch({ type: 'decrement' })} style={{ marginLeft: 8 }}>
        -
      </Button>
      <Button onCl ick={() => dispatch({ type: 'setStep', payload: 5 })} style={{ marginLeft: 8 }}>
        Установить шаг 5
      </Button>
    </>
  );
};

export default ReducerDemo;

useReducer обеспечивает предсказуемость и удобство масштабирования при сложной логике состояния, особенно в комбинации с Ant Design компонентами, где требуется синхронизация нескольких UI элементов.


Резюме подходов

  • Локальное состояние (useState) — быстрый и простой способ управления отдельными компонентами.
  • Form API (Form.useForm) — удобный инструмент для синхронизации данных и валидации форм.
  • Таблицы и пагинация — состояние управляется через useState или Redux для динамического обновления данных.
  • Модальные окна и загрузкаopen и loading свойства позволяют гибко контролировать отображение и взаимодействие.
  • useReducer — оптимальный вариант для сложных и взаимосвязанных состояний.

Сочетание этих методов позволяет создавать сложные интерфейсы с высокой интерактивностью, сохраняя код читаемым и поддерживаемым.