Как визуализировать поля формы React Final в цикле - PullRequest
0 голосов
/ 08 июля 2019

Я пытаюсь визуализировать несколько полей React Final Form в цикле. У меня есть массив объектов следующим образом:

export const check_groups = [
    {
        name: "Mechanics",
        checks: [
            {typeName: "Boolean", title: "Clutch", icon: "fa fa-tire-rugged", key: "clutch", mandatory: true}
        ]
    },
    {
        name: "Maintenance & control",
        checks: [
            {typeName: "Boolean", title: "Recent timing belt", icon: "fal fa-cogs", key: "recent_timing_belt", mandatory: false},
            {typeName: "Boolean", title: "Recent service", icon: "fal fa-oil-can", key: "recent_service", mandatory: false}
        ]
    }
];

и я хочу визуализировать поле для каждого объекта в этом массиве. Таким образом, я отображаю массив через функцию lodash map и отображаю новый компонент следующим образом:

return check_groups.map(group => {
                return <div key={UUID.v4()}>
                    <div className="text-base w-full flex flex-row mb-1">
                        <div className="p-1 text-blue-dark">{group.name}</div>
                    </div>
                    {map(group.checks, (check) => {
                        switch (check.typeName) {
                            case "RegEx":
                                break;
                            case "Numeric":
                                break;
                            case "Boolean":
                                const name = `checks[${check.title}]`;
                                return (
                                    <TriStateItemField key={check.title} name={name} label={check.title} icon={check.icon} values={values}/>
                                );

                            default:
                                break;
                        }
                    })}
                </div>
            })

TriStateItemField - это просто компонент, который визуализирует поле формы и передает данные в компонент представления (TriStateItem):

<Field name={name}
               validate={(validators) ? composeValidators(...validators) : false}
               data-tip={dataTip}
               data-for={dataFor}>

            {({input, meta}) => {
                return (
                    <TriStateItem label={label}
                                  name={name}
                                  type={type}
                                  className={className}
                                  style={style}
                                  hasError={meta.touched && meta.error}
                                  error={meta.error}
                                  placeholder={placeholder}
                                  disabled={disabled}
                                  helperText={helperText}
                                  icon={icon}
                                  {...input}
                                  {...meta}

                    />
                )
            }}
        </Field>

И TriStateItem - это компонент, который показывает данные:

class TriStateItem extends Component {
    renderValue(value){
        let new_value = undefined;
        if (value === "") new_value = true;
        if (value !== "" && value) new_value = false;
        if (value !== "" && !value) new_value = undefined;
        return new_value;
    }

    render() {
        const {label, icon, className, dataTip, dataFor, onChange, disabled, value, hasError, valid} = this.props;
        const isValid = value !== "";
        return (
            <div
                className={`flex flex-row justify-between w-full hover:bg-blue-200 bg-gray-100 cursor-pointer p-2 border-r-2 border-solid ${valid ? "border-transparent" : "border-red-500"} ${isValid ? "border-green-500" : ""} ${hasError ? "bg-red-100" : "bg-transparent" } ${className} ${disabled ? "opacity-60" : ""}`}
                onClick={() => onChange(this.renderValue(value))}>
                <div className="flex flex-row">
                    {icon !== undefined && <div className="pr-2"><i className={`text-gray-500 ${icon}`}/></div>}
                    <div>{label}</div>
                </div>
                {value === "" && <i className="fal fa-circle text-gray-500" style={{fontSize: 16}}/>}
                {value !== "" && value && <i className="fal fa-check text-green-500" style={{fontSize: 16}}/>}
                {value !== "" && !value && <i className="fal fa-times text-red-600" style={{fontSize: 16}}/>}
            </div>
        )
    }

Проблема в том, что я получаю сообщение об ошибке следующим образом:

Uncaught Invariant Violation: Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate. React limits the number of nested updates to prevent infinite loops.

, а затем:

The above error occurred in the <Field> component:
    in Field (at TriStateItemField.js:8)

Вот пример песочница . Если вы откроете консоль, вы увидите ту же ошибку.

Есть идеи, что я делаю не так?

1 Ответ

0 голосов
/ 09 июля 2019

I ответил на это на Github .

Я думаю, что библиотека UUID (я никогда не использовал ее) генерирует новый ключ для вашего div на каждом рендере, которыйвызывает бесконечный рендеринг, потому что он отменяет регистрацию всех ваших полей и перерегистрацию их, что требует перерисовки всей формы, что генерирует новые ключи, которые отменяют регистрацию / перерегистрацию всех ваших полей, что ......

Изменение index.js:165 до <div key={group.name}> исправляет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...