Как работать с несколькими полями в redux-form?

Я использую redux-form. Мне понятно, как обстоят дела с формами, в которых несколько полей. То есть делаем такую форму:

<form onSubmit={handleSubmit}>
    <Field name={'first'} ... />
    <Field name={'second'} ... />
    <Field name={'third'} ... />
</form>

А потом вот так вытаскиваем данные, по-отдельности с каждого поля:

let first = formData.first;
...

Сейчас я пытаюсь сделать форму, в которой количество полей динамическое, а сами поля одного рода. Ну, например, у меня есть форма, в которой текст перемежается с полями для вставки пропущенных слов. Что-то такое:

Маша пошла гулять на речку и взяла [......]. А потом она встретила колобка и [......] его.

И сейчас я вставляю эти <Field/> в цикле и каждому присваиваю отдельное имя. Из-за этого очень сложно как создавать форму, так и извлекать данные. Приходится высчитывать количество полей и делать что-то такое:

for (let i = 0; i < formData.length; i = i + 1) {
    console.log(formData['fieldNumber' + (i + 1)]);
}

Так вот обязательно ли мне задавать для каждого такого поля индивидуальное имя? Как мне избежать такого нагромождения кода?


Ответы (1 шт):

Автор решения: Zhenyria

Существует два варианта решения этой задачи.

1. Использование getFormValues()

Выглядит это вот так:

const mapStateToProps = (state) => ({
    formValues: getFormValues('myReduxForm')(state)
});

export default connect(mapStateToProps, {})(MyReduxForm);

В параметрах getFormValues мы указываем название интересующей нас формы. Это же название мы указывали для формы, когда подключали её к redux-form. Мы получаем formValues, это объект, который содержит данные формы:

{
    firstField: 'first',
    secondField: 'second',
    thirdField: 'third'
}

Дальше не составит никакого труда получить содержимое в виде массива: Object.values(formData).

2. Использование специального имени для <Field/>

Этот способ я рекомендую. Лично мне он показался проще.

Итак, если мы создаём <Field/> в цикле, то, как правило, мы не можем создавать для каждого поля уникальное имя. Единственное что у нас есть уникальное, это индекс. В таком случае нам следует создавать <Field/> следующим способом:

<Field name={'keyword.' + index}/>

Обратите внимание, что сначала должно идти общее для всех полей слово, потом обязательно точка, а потом уже индекс (вероятно, можно ставить вместо индекса другие уникальные значения, например буквы, я не проверял, но скорее всего так тоже будет работать), то есть имя каждого поля должно иметь такой вид: [ключевое слово].[индекс].

Чтобы получить данные полей формы в onSubmit(), мы делаем следующее:

const onSubmit = (formData) => {
    const fieldsData = formData.keyword;

    // ...
}

То есть мы вытаскиваем из объекта formData массив с данными формы. Этот массив мы вытаскиваем по тому же имени, какое указывали для всех полей перед точкой: [ключевое слово].[индекс].

Например. Мы создаём в цикле три поля <Field/>. Мы указываем имя для них следующим образом: <Field name={'myField.' + index}/>. Теперь, когда мы захотим получить данные формы, мы поступаем следующим образом:

const onSubmit = (formData) => {
    const fieldsData = formData.myField;
    // ...
}

В массиве fieldsData будет находится содержимое всех трёх полей.

→ Ссылка