如何在循环中渲染React Final表单字段

时间:2019-07-08 11:54:23

标签: javascript reactjs react-final-form

我正在尝试在一个循环中渲染多个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)

这里是sandbox上的示例。如果打开控制台,则会看到相同的错误。

知道我做错了什么吗?

1 个答案:

答案 0 :(得分:0)

answered this on Github

  

我认为UUID库(我从未使用过)正在生成新密钥   对于每个渲染上的div,这会导致无限渲染,因为   它正在注销所有字段并重新注册它们,这   需要重新提交整个表单,这会生成新的密钥,   注销/重新注册您的所有字段,      

index.js:165更改为<div key={group.name}>即可解决。