> Как реализовать динамическое добавление полей в формах с помощью Formik (React)

Уровень: senior · Роль: frontend · Категория: Технические вопросы

Компании: ДиджиталСектор

Стек: React

> Пример ответа

Короткий ответ

Для динамического добавления полей в Formik используется массив значений в initialValues и компонент FieldArray. Он предоставляет методы push, remove, insert для управления полями. Каждое поле должно иметь уникальный ключ (обычно индекс). Важно правильно настроить валидацию через Yup или кастомную функцию, учитывая динамическую структуру. FieldArray автоматически синхронизирует состояние формы с React-компонентами.

Подробное объяснение

Formik решает задачу динамических полей через абстракцию FieldArray, которая работает с массивом объектов в состоянии формы. Основная идея - хранить список полей как массив, где каждый элемент - объект с полями формы. FieldArray предоставляет иммутабельные методы: push (добавить), remove (удалить по индексу), insert (вставить), swap (поменять местами). При каждом изменении Formik пересоздаёт массив, что триггерит ререндер.

Ключевой момент - генерация уникальных идентификаторов для каждого элемента массива. Без них React не сможет эффективно обновлять DOM при удалении/добавлении элементов. Обычно используют индекс массива, но при сортировке или вставке это может вызвать баги. Лучше добавить поле id (например, uuid) и использовать его как key.

Валидация для динамических полей настраивается через Yup: yup.array().of(yup.object().shape({...})). Можно также использовать кастомную validate функцию, которая получает весь массив значений.

На практике

При реализации нужно:

  1. Определить структуру initialValues с пустым массивом: items: []
  2. Использовать FieldArray с name="items"
  3. Внутри FieldArray рендерить поля через map, передавая index и field name
  4. Для добавления - push({ field1: '', field2: '' })
  5. Для удаления - remove(index)
  6. Для key использовать уникальный id, а не индекс

Продвинутые сценарии включают:

  • Вложенные FieldArray (массив в массиве)
  • Асинхронную загрузку начальных значений
  • Кастомные компоненты полей с поддержкой FieldArray
  • Оптимизацию через React.memo для больших списков

Пример кода

JSX
import { Formik, Form, FieldArray, Field } from 'formik';
import * as Yup from 'yup';
const validationSchema = Yup.object().shape({
items: Yup.array().of(
Yup.object().shape({
name: Yup.string().required('Обязательно'),
quantity: Yup.number().min(1, 'Минимум 1').required()
})
)
});
function DynamicForm() {
return (
<Formik
initialValues={{ items: [{ name: '', quantity: 1 }] }}
validationSchema={validationSchema}
onSubmit={values => console.log(values)}
>
{({ values }) => (
<Form>
<FieldArray name="items">
{({ push, remove, form }) => (
<div>
{values.items.map((item, index) => (
<div key={index} style={{ display: 'flex', gap: 8 }}>
<Field name={`items.${index}.name`} placeholder="Название" />
<Field name={`items.${index}.quantity`} type="number" />
<button type="button" onClick={() => remove(index)}>Удалить</button>
</div>
))}
<button type="button" onClick={() => push({ name: '', quantity: 1 })}>
Добавить
</button>
</div>
)}
</FieldArray>
<button type="submit">Отправить</button>
</Form>
)}
</Formik>
);
}

Как отвечать на собеседовании

Начни с краткого определения FieldArray и его роли. Объясни, что Formik хранит динамические поля как массив объектов в состоянии. Упомяни методы push/remove и важность уникальных ключей. Покажи понимание валидации через Yup. Если спросят про производительность, скажи про React.memo и избегание анонимных функций в render props. Для senior-уровня добавь про кастомные хуки для сложной логики и интеграцию с бэкендом.

Что проверяет интервьюер

  • Понимание работы Formik с массивами
  • Умение настраивать валидацию для динамических структур
  • Знание React-паттернов (keys, иммутабельность)
  • Способность объяснить trade-off между индексом и uuid как key
  • Опыт с реальными кейсами (вложенные формы, асинхронная загрузка)

Типичные ошибки

  • Использование индекса массива как key при наличии операций удаления/вставки - приводит к багам с фокусом и состоянием полей
  • Забывают обновлять initialValues при изменении количества полей
  • Неправильная вложенность имён полей (например, items[0].name вместо items.0.name)
  • Игнорирование валидации для динамических полей - Yup схема должна быть адаптирована
  • Мутация массива напрямую вместо использования методов FieldArray

> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?

Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью