У меня есть компонент React (первоначально написанный кем-то другим), который отображает форму для человека (редукционная форма). Недавно я изменил компонент на FieldArray (компонент редукционной формы).
У меня есть проверка для поля электронной почты, которая влияет на className для поля электронной почты (красный цвет, когда электронная почта неправильно отформатирована, в противном случае — черный). Это работало нормально, когда это не был FieldArray, но теперь он проверяет все поля электронной почты сразу из-за
// (in constructor)
this.email = React.createRef();
// (in Field)
ref={props.parent.email}
, то есть props.parent.email является глобальной/статической ссылкой.
Пример: Есть два человека. Одно из них имеет неправильно отформатированное электронное письмо, но оба письма отображаются красным цветом.
Насколько я понимаю, мне нужно было бы иметь динамическую ссылку, но это не сработало так, как я пытался.
ref={`${person}.email.ref`}
Ошибка
«Функциональные компоненты не могут иметь ссылок. Вы хотели использовать React.forwardRef()?»
Я не нашел ничего полезного в forwardRef относительно FieldArray, кроме того факта, что это допустимая опора.
Моя цель: когда несколько человек создаются пользователем и/или загружаются из магазина Redux, иметь возможность отображать каждое правильно отформатированное электронное письмо черным цветом, а каждое неправильно отформатированное электронное письмо красным.
Любая помощь приветствуется!
import React from "react";
import { Field, reduxForm, FieldArray } from "redux-form";
import { connect } from "react-redux";
import classNames from 'classnames'
import { MAIL_PATTERN } from "../some_file";
import MoreGeneralComponent from "../some_other_file";
const renderField = ({ input, label, type, options, className, meta: { touched, error }, style, disabled, hidden }) => (
<div style={style}>
<label>{label}</label>
<div>
<input {...input} disabled={disabled ? true : false} hidden={hidden ? true : false} type={type} placeholder={label} className={className} />
</div>
</div>
);
const renderPerson = ({ fields, meta: { error, submitFailed }, ...props }) => {
setTimeout(props.validate(fields));
return (
<ul className="personlist">
{fields.map((person, index) => (
<li key={index} className="person">
<h4>Person #{index + 1}</h4>
<Field
component={renderField}
type="text"
ref={props.parent.email}
className={classNames({invalid: !props.parent.state.validEmail})}
validate={props.parent.validateEmail}
name={`${person}.email`}
label="Email"
key={`${person}.email`}
></Field>
<button type="button" onClick={() => fields.remove(index)}>
Remove
</button>
</li>
))}
{(!(fields.length >= props.max)) && (
<li className="addperson">
<button
type="button"
onClick={() => fields.push({})}
disabled={fields.length >= props.max}
>
Add Person
</button>
{submitFailed && error && <span>{error}</span>}
</li>)}
</ul>
);
};
class Person extends MoreGeneralComponent {
constructor(props) {
super(props);
if (this.state.ready) {
this.max = 4;
this.data = ["email"];
this.email = React.createRef();
}
}
validate = fields => {
if (!fields || !fields.getAll()) {
return;
}
let valid = true;
fields.getAll().forEach(field => {
for (let d of this.data) {
if (!field[d] || field[d].length < 2) {
valid = false;
return;
} else if (d === "email") {
valid = field[d] && MAIL_PATTERN.test(field[d]) ? valid : undefined;
}
}
});
if (valid !== this.state.valid) {
this.setState({
valid: valid
});
}
};
validateEmail = (value) => {
const valid = value && MAIL_PATTERN.test(value) ? value : undefined;
this.setState({validEmail: !!valid});
return valid
}
renderQuestion() {
return (
<div className={style.question}>
<fieldset>
<FieldArray
name="persons"
component={renderPerson}
props={{ max: this.max, validate: this.validate, parent: this }}
rerenderOnEveryChange={true}
/>
</fieldset>
</div>
);
}
}
const mapStateToProps = s => {
const persons = s.persons
var initialValuesPersons = []
persons.map(item => initialValuesPersons.push({
"email": item.email || ""
}))
var initialValues = { "persons": initialValuesPersons}
return {
initialValues,
formdata: s.form
}
}
export default connect(mapStateToProps, null)(reduxForm(
{
form: 'person',
destroyOnUnmount: false,
enableReinitialize: true,
keepDirtyOnReinitialize: true
})(Person))