Formik

Formik — это популярная библиотека для управления состоянием форм в React-приложениях. Она упрощает обработку данных формы, валидацию и интеграцию с UI-компонентами. Formik позволяет избегать громоздкого ручного управления состоянием и обработчиков событий, делая код чище и более предсказуемым.

Создание формы с использованием Formik

Для начала работы необходимо импортировать Formik и Form из библиотеки:

import { Formik, Form, Field, ErrorMessage } from 'formik';

Базовый пример формы:

<Formik
  initialValues={{ email: '', password: '' }}
  onSub mit={(values) => {
    console.log(values);
  }}
>
  {({ isSubmitting }) => (
    <Form>
      <div>
        <label htmlFor="email">Email</label>
        <Field type="email" name="email" />
        <ErrorMessage name="email" component="div" />
      </div>

      <div>
        <label htmlFor="password">Пароль</label>
        <Field type="password" name="password" />
        <ErrorMessage name="password" component="div" />
      </div>

      <button type="submit" disabled={isSubmitting}>
        Отправить
      </button>
    </Form>
  )}
</Formik>

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

  • initialValues задает начальное состояние полей формы.
  • Field автоматически связывает поле ввода с состоянием Formik.
  • ErrorMessage отображает ошибки валидации, если они существуют.
  • isSubmitting показывает состояние отправки формы.

Валидация формы

Formik поддерживает синхронную и асинхронную валидацию. Наиболее популярный способ — использование библиотеки Yup:

import * as Yup from 'yup';

const validationSchema = Yup.object({
  email: Yup.string().email('Неверный формат email').required('Обязательное поле'),
  password: Yup.string().min(6, 'Минимум 6 символов').required('Обязательное поле'),
});

В Formik это подключается через свойство validationSchema:

<Formik
  initialValues={{ email: '', password: '' }}
  validationSchema={validationSchema}
  onSub mit={(values) => console.log(values)}
>

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

Formik предоставляет удобные методы для работы с полями и состоянием формы:

  • setFieldValue(name, value) — программное изменение значения поля.
  • setFieldTouched(name, touched) — установка состояния «прикосновения» к полю.
  • resetForm() — сброс формы к начальным значениям.

Кастомные компоненты удобно интегрировать через useField хук:

import { useField } from 'formik';

const TextInput = ({ label, ...props }) => {
  const [field, meta] = useField(props);
  return (
    <div>
      <label htmlFor={props.id || props.name}>{label}</label>
      <input {...field} {...props} />
      {meta.touched && meta.error ? <div>{meta.error}</div> : null}
    </div>
  );
};

Использование:

<Formik initialValues={{ username: '' }} onSub mit={console.log}>
  <Form>
    <TextInput label="Имя пользователя" name="username" type="text" />
    <button type="submit">Отправить</button>
  </Form>
</Formik>

Управление динамическими формами

Formik отлично справляется с массивами полей с помощью компонента FieldArray. Пример:

import { FieldArray } from 'formik';

<FieldArray name="friends">
  {({ push, remove, form }) => (
    <div>
      {form.values.friends.map((friend, index) => (
        <div key={index}>
          <Field name={`friends.${index}.name`} placeholder="Имя друга" />
          <button type="button" onCl ick={() => remove(index)}>Удалить</button>
        </div>
      ))}
      <button type="button" onCl ick={() => push({ name: '' })}>Добавить друга</button>
    </div>
  )}
</FieldArray>

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

  • push() добавляет новый элемент в массив.
  • remove() удаляет элемент по индексу.
  • Поля массива синхронизируются с Formik автоматически.

Асинхронная валидация и отправка

Formik поддерживает асинхронную обработку:

<Formik
  initialValues={{ username: '' }}
  validate={async (values) => {
    const errors = {};
    const isAvailable = await checkUsernameAvailability(values.username);
    if (!isAvailable) errors.username = 'Имя пользователя занято';
    return errors;
  }}
  onSub mit={async (values, { setSubmitting }) => {
    await sendFormData(values);
    setSubmitting(false);
  }}
>

Важно: всегда управлять состоянием isSubmitting, чтобы предотвратить многократную отправку формы.

Интеграция с UI-библиотеками

Formik легко интегрируется с компонентами Radix UI, Material UI или Chakra UI через кастомные поля и хук useField. Пример с Radix UI:

import * as Switch from '@radix-ui/react-switch';
import { useField } from 'formik';

const FormSwitch = ({ name }) => {
  const [field, , helpers] = useField(name);
  return (
    <Switch.Root
      checked={field.value}
      onCheckedCha nge={(val) => helpers.setValue(val)}
    >
      <Switch.Thumb />
    </Switch.Root>
  );
};

Поддержка вложенных объектов и сложных структур

Formik позволяет работать с глубоко вложенными данными с помощью точечной нотации:

initialValues={{
  user: { firstName: '', lastName: '' },
}}

<Field name="user.firstName" />
<Field name="user.lastName" />

Ошибки и валидация поддерживают такую же структуру, позволяя точно указывать путь к полю.

Полезные хуки

  • useFormikContext() — доступ к контексту формы в любом компоненте.
  • useField(name) — управление отдельным полем с метаданными.
  • useFormik() — полный доступ к методам и состоянию формы для кастомной логики.

Резюме

Formik предоставляет полный набор инструментов для управления формами в React: автоматическое связывание полей, валидация, поддержка массивов, асинхронных действий и интеграция с внешними UI-библиотеками. Его гибкая архитектура позволяет создавать как простые формы, так и сложные динамические структуры с минимальным количеством повторяющегося кода.