实现redux-form下拉依赖校验时触发Maximum update depth exceeded错误如何解决
问题原因
你的代码触发无限循环的核心原因有三个:
- HOC包裹顺序错误:你先给组件套了
reduxForm,再套connect,redux-form的状态更新会触发外层connect重新计算返回新props,导致表单组件重渲染,重渲染又触发redux-form的状态校验更新,形成死循环。redux-form官方要求的HOC执行顺序是先执行connect,再套reduxForm。 - 内联函数导致不必要重渲染:role字段的Field组件直接传入了内联箭头函数作为
onChange,每次组件渲染都会生成新的函数引用,触发Field组件重复渲染,进一步加剧循环。 - 多余的表单值更新:你在role的onChange回调里,只要选中
user角色就强制修改密码和确认密码为空,哪怕这两个字段已经是空值,也会触发redux-form状态更新,加大循环概率。
修复步骤
1. 调整HOC包裹顺序
把connect逻辑放到reduxForm包裹之前:
const selector = formValueSelector(formNames.USER); // 先做connect const ConnectedUsersForm = connect((state) => { const selectedRole = selector(state, "role"); return { selectedRole, }; })(UsersForm); // 再套reduxForm UsersForm = reduxForm({ form: formNames.USER, })(ConnectedUsersForm);
2. 提取内联onChange为类方法
把onChange逻辑从Field的props里提取为组件的实例方法,避免每次渲染生成新的函数引用,同时加判断避免不必要的表单值修改:
// 组件内部定义方法(类属性写法,不用额外bind) handleRoleChange = (event) => { const { change, password, confirmPassword } = this.props; // 只有角色是user,且密码字段不为空的时候才执行修改 if (event.target.value === "user" && (password !== "" || confirmPassword !== "")) { change("password", ""); change("confirmPassword", ""); } } // Field组件引用方法 <Field id="user-form-roles" name="role" component={userRoleSelectField} className={style.inputField} fullWidth={true} items={getRoles(intl)} label={i18n({ id: "users.role" })} onChange={this.handleRoleChange} />
3. 可选优化
如果你的emailRequiredForAdmin("role")是工厂函数,每次执行都会生成新的校验函数,建议把生成的校验函数提取到组件外部,或者存在组件实例属性上,避免每次渲染都传递新的validate数组触发Field重复渲染。
内容的提问来源于stack exchange,提问作者avi
相关产品推荐
相关产品推荐

