Как работать с несколькими полями в 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 шт):
Существует два варианта решения этой задачи.
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 будет находится содержимое всех трёх полей.