redux-form中SubmissionError无法更新错误状态问题
我之前也踩过这个一模一样的坑!明明严格按照官方文档抛出了SubmissionError,结果Field组件的errors属性始终是undefined,在v6和v7版本里都碰到过,后来排查出几个关键问题,你可以对照着检查下:
1. 确认SubmissionError的格式完全正确
redux-form的SubmissionError要求接收一个键为字段名、值为错误信息的对象(也可以包含_error字段用于全局错误)。如果你抛错的格式不对,redux-form无法将错误映射到对应Field。
正确的写法应该是:
throw new SubmissionError({ email: '邮箱格式不正确或未注册', // 这里的键要和Field的name完全一致 // _error: '登录失败,请重试' // 可选的全局错误 });
如果你只是抛出new SubmissionError('登录失败')这种字符串格式,redux-form根本没法识别到具体字段的错误,自然Field的errors就是undefined。
2. 检查Field的name属性和错误字段名完全匹配
这个细节很容易忽略:你的Field组件的name属性,必须和SubmissionError里的键完全一致(包括大小写)。比如Field的name是userEmail,但你抛错时写的是email: '错误信息',字段名不匹配的话,redux-form就无法把错误绑定到对应的Field上。
3. 确保用redux-form的handleSubmit包裹提交函数
你必须使用redux-form通过props传递的handleSubmit来包裹你的自定义提交函数,而不是直接给form的onSubmit绑定自己的函数。因为redux-form需要通过handleSubmit来捕获SubmissionError,并把错误分发到表单的state中,进而传递给Field组件。
正确的写法:
<form onSubmit={this.props.handleSubmit(this.onEmailSubmit)}>
如果直接写<form onSubmit={this.onEmailSubmit}>,抛出的SubmissionError根本不会被redux-form处理,Field自然拿不到错误信息。
4. 确认Field组件正确读取meta中的error属性
不管你用默认的input组件还是自定义组件,Field的错误信息是存在meta对象里的,而不是直接在props根层级。比如自定义Field组件要这么写:
const CustomInput = ({ input, meta: { touched, error } }) => ( <div> <input {...input} /> {/* 只有当字段被触碰过(touched为true)时再显示错误,避免一开始就展示错误 */} {touched && error && <span className="error-text">{error}</span>} </div> );
如果你直接从props里取error而不是meta.error,那肯定会拿到undefined。
额外排查:确认redux store已正确配置formReducer
如果以上几点都没问题,那可能是你的redux store没正确集成redux-form的reducer。必须在根reducer里加入formReducer,否则redux-form的state无法被正确管理:
import { combineReducers, createStore } from 'redux'; import { reducer as formReducer } from 'redux-form'; const rootReducer = combineReducers({ // 其他reducer... form: formReducer // 这一步必不可少 }); const store = createStore(rootReducer);
完整的正确示例
这里给你一个可以直接参考的完整登录表单示例:
import React, { Component } from 'react'; import { reduxForm, Field, SubmissionError } from 'redux-form'; class Login extends Component { onEmailSubmit = (values) => { // 模拟异步登录验证 return new Promise((resolve, reject) => { setTimeout(() => { if (values.email !== 'test@example.com') { // 字段名和Field的name完全匹配 reject(new SubmissionError({ email: '该邮箱未注册' })); } else { resolve('登录成功'); } }, 1000); }); }; render() { const { handleSubmit } = this.props; return ( <form onSubmit={handleSubmit(this.onEmailSubmit)} className="login-form"> <div className="form-group"> <label>邮箱</label> <Field name="email" component="input" type="email" placeholder="请输入邮箱" /> {/* 用自定义组件展示错误 */} <Field name="email" component={(props) => ( <div> <input {...props.input} type="email" className="form-control" /> {props.meta.touched && props.meta.error && ( <small className="text-danger">{props.meta.error}</small> )} </div> )} /> </div> <button type="submit" className="btn btn-primary">登录</button> </form> ); } } // 必须指定唯一的form名称 export default reduxForm({ form: 'login' })(Login);
你可以按照上面的步骤逐一排查,应该就能解决Field的errors为undefined的问题了。
内容的提问来源于stack exchange,提问作者gregRV

