reactjs - 使用 redux 表单字段数组超出更新深度
问题描述
我正在使用 Redux 表单字段数组,当向字段数组添加新元素时,应用程序由于以下错误而崩溃:
超过最大更新深度。当组件在 componentWillUpdate 或 componentDidUpdate 中重复调用 setState 时,可能会发生这种情况。React 限制了嵌套更新的数量以防止无限循环。
组件代码为:
import React from 'react';
import {reduxForm, Field, FieldArray} from 'redux-form';
import {
Button,
CircularProgress,
Grid,
}from '@material-ui/core';
import {Link} from 'react-router-dom';
import { makeStyles } from '@material-ui/styles';
import {FileInput, SelectInput, LocationInput, TextInput } from './FormFields';
import { SERVICES } from '../Routing/routes';
const userStyles = makeStyles(theme=>({
section:{
maxWidth:theme.breakpoints.values.md,
margin:'0 auto',
},
form:{
position:'relative',
paddingBottom:theme.spacing(8)
},
actionButtons:{
position:'fixed',
bottom:0,
right:0,
padding:theme.spacing(3),
backgroundColor:theme.palette.secondary.main,
borderTop: `1px solid ${theme.palette.primary.main}`
},
button:{
marginLeft:theme.spacing(1)
}
}));
const ProviderServiceForm = (props) =>{
const classes = userStyles();
const {handleSubmit, onFormSubmit, pending} = props;
const renderSubmitIcon = () =>{
if(pending)
return <CircularProgress color="primary" size={20}/>
else
return
}
const renderField = ({ input, label, type, meta: { touched, error } }) => (
<div>
<label>{label}</label>
<div>
<input {...input} type={type} placeholder={label} />
{touched && error && <span>{error}</span>}
</div>
</div>
);
const renderVariants = ({ fields, meta: { error, submitFailed } }) =>(
<ul>
<li>
<Button onClick={() => fields.push({})}>Añadir</Button>
{submitFailed && error && <span>{error}</span>}
</li>
{fields.map((variant,index)=>(
<li key={index}>
<h4>Variante #{index + 1}</h4>
<Field
name={`${variant}.title`}
type="text"
component={renderField}
label="First Name"
/>
</li>
))}
</ul>
);
return(
<div className={classes.section}>
<form onSubmit={handleSubmit(onFormSubmit)} className={classes.form}>
<input type="hidden" value="something"/>
<FieldArray name="variants" component={renderVariants}/>
<Field name="placeName" label="Nombre del centro o del lugar" component={TextInput} autoComplete="organization"/>
<Field name="address" label="Dirección" component={LocationInput} autoComplete="off"/>
<Field name="adressDetails" label="Planta, Piso, Puerta..." component={TextInput} autoComplete="address-level3"/>
<Field name="category" label="Categoría de servicios" component={SelectInput} autoComplete="category"/>
<Field name="image" type="file" label="Sube una foto..." component={FileInput}/>
<Grid container className={classes.actionButtons} justify="flex-end">
<Link to={SERVICES} style={{ textDecoration: 'none' }}>
<Button type="submit" variant="outlined" color="primary" disabled={pending}>Cancelar</Button>
</Link>
<Button type="submit" variant="contained" color="primary" className={classes.button} disabled={pending} startIcon={renderSubmitIcon()}>Guardar</Button>
</Grid>
</form>
</div>
)
}
const validate = (formValues) =>{
const errors = {}
if (!formValues.variants || !formValues.variants.length) {
errors.variants = { _error: 'Almenos tienes que introducir una variante' };
} else {
const variantsArrayErrors = [];
formValues.variants.forEach((variant, variantIndex) => {
const variantErrors = {};
if (!variant || !variant.title) {
variantErrors.title = 'Tienes que introducir un título';
variantsArrayErrors[variantIndex] = variantErrors;
}
if (!variant || !variant.price > 0) {
variantErrors.price = 'Tienes que poner un precio superior a 0€';
variantsArrayErrors[variantIndex] = variantErrors;
}
});
if (variantsArrayErrors.length) {
errors.variants = variantsArrayErrors;
}
}
if (!formValues.placeName){
errors.placeName = 'Debes intriducir el nombre del centro o lugar'
}
if (!formValues.address){
errors.address = 'Debes intriducir una dirección válida'
}
if(!formValues.category){
errors.category = 'Tienes que seleccionar una categoría';
}
if(!formValues.image){
errors.image = 'Debes seleccionar una imagen de Portada';
}
return errors;
}
export default reduxForm({
form:'ProviderServiceForm',
validate,
})(ProviderServiceForm);
我认为当我执行以下行代码时会出现错误:
<Button onClick={() => fields.push({})}>Añadir</Button>
当我推送一个新值时,组件会无限地重新渲染。
我很惊讶,因为大部分字段数组代码都是从 redux 表单文档中复制的:
https://redux-form.com/8.3.0/examples/fieldarrays/
知道如何解决吗?
提前致谢。
解决方案
这部分代码是错误的
onSubmit={handleSubmit(onFormSubmit)}
改用箭头函数将解决问题:
onSubmit={() => handleSubmit(onFormSubmit)}
当您在渲染函数中编写函数时()
,在页面的每次渲染中,该函数都会调用并导致越来越多的状态更改。
推荐阅读
- python - 如何更改到一个甚至不存在的新目录?
- java - 检索帐户时出错 java.lang.IllegalStateException:没有当前的触碰付款帐户
- python - 对数据框中的值执行功能并替换
- javascript - Facebook 嵌入视频播放器 api 不在本地 html 文件中呈现 iframe 视频输出
- python - 如何让 Jupyter Notebook 内核在 Kubernetes 中抛出内存不足错误
- django - saveloan() 得到了一个意外的关键字参数“loanname”
- php - 如何在 symfony 中编辑上传的图像
- javascript - 在 sweetalert onOpen 函数中使用路由器推送 - Vue2
- security - 是后门类型的漏洞还是恶意软件?
- scala - spark解析内部json值字段并创建一个新列