我正在尝试在一个循环中渲染多个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上的示例。如果打开控制台,则会看到相同的错误。
知道我做错了什么吗?
答案 0 :(得分:0)
我认为UUID库(我从未使用过)正在生成新密钥 对于每个渲染上的div,这会导致无限渲染,因为 它正在注销所有字段并重新注册它们,这 需要重新提交整个表单,这会生成新的密钥, 注销/重新注册您的所有字段,
将
index.js:165
更改为<div key={group.name}>
即可解决。