redux-form提交时未处理Promise拒绝,需将ApiClient错误返回至表单展示
解决redux-form/immutable中Api错误传递给表单的问题
我来帮你搞定这个问题!在redux-form/immutable里把Api返回的错误传递给表单展示其实很直接,核心就是正确使用SubmissionError来包装你的Api错误,让redux-form能识别并映射到对应的字段或者全局错误上。下面我用你的登录表单场景一步步说明:
核心思路
redux-form的onSubmit函数需要返回一个Promise,当你在Promise的catch块中抛出SubmissionError时,redux-form会自动将错误信息绑定到表单的字段或全局错误上,无需手动更新state。
步骤1:处理Api错误并抛出SubmissionError
首先,你需要在提交函数中捕获ApiClient的错误,将Api返回的错误格式映射成redux-form能识别的结构,然后抛出SubmissionError。
import { SubmissionError } from 'redux-form/immutable'; // 假设这是你的ApiClient登录方法 const apiClient = { login: (email, password) => { // 模拟Api请求,这里替换成你的真实Api调用 return fetch('/api/login', { method: 'POST', body: JSON.stringify({ email, password }) }).then(response => { if (!response.ok) { return response.json().then(err => Promise.reject(err)); } return response.json(); }); } }; // 表单的提交处理函数 const handleLoginSubmit = (values) => { // 因为用了immutable,所以用get方法获取字段值 const email = values.get('email'); const password = values.get('password'); return apiClient.login(email, password) .catch(apiError => { // 构建redux-form需要的错误对象 const formErrors = {}; // 这里根据你的Api返回格式调整,比如Api返回{ errors: { email: 'xxx', password: 'xxx' } } if (apiError.errors) { // 将Api的字段错误映射到表单字段 Object.entries(apiError.errors).forEach(([field, message]) => { formErrors[field] = message; }); } else { // 如果是全局错误(比如服务器内部错误),用_error字段 formErrors._error = '登录失败,请稍后重试'; } // 抛出SubmissionError,redux-form会自动处理错误展示 throw new SubmissionError(formErrors); }); };
步骤2:在表单组件中展示错误
接下来,在你的登录表单组件里,通过redux-form提供的props和Field组件来展示字段错误和全局错误:
import React from 'react'; import { Field, reduxForm } from 'redux-form/immutable'; const LoginForm = ({ handleSubmit, error, submitting }) => ( <form onSubmit={handleSubmit(handleLoginSubmit)}> {/* 展示全局错误 */} {error && <div className="alert alert-danger">{error}</div>} <div className="form-group"> <label>邮箱</label> <Field name="email" component="input" type="email" className="form-control" /> {/* 展示邮箱字段的错误 */} <Field name="email" component={({ meta }) => ( meta.touched && meta.error && <span className="text-danger">{meta.error}</span> )} /> </div> <div className="form-group"> <label>密码</label> <Field name="password" component="input" type="password" className="form-control" /> {/* 展示密码字段的错误 */} <Field name="password" component={({ meta }) => ( meta.touched && meta.error && <span className="text-danger">{meta.error}</span> )} /> </div> <button type="submit" className="btn btn-primary" disabled={submitting}> {submitting ? '登录中...' : '登录'} </button> </form> ); // 用reduxForm装饰组件,指定表单唯一标识 export default reduxForm({ form: 'loginForm' })(LoginForm);
关键注意点
- 错误字段名匹配:
SubmissionError中的键必须和Field组件的name属性完全一致,否则错误无法绑定到对应字段。 - Immutable对象处理:因为用了
redux-form/immutable,表单的values是Immutable对象,所以要用get方法获取字段值,不能直接用.访问。 - 必须返回Promise:提交函数一定要返回Promise,这样redux-form才能正确处理异步提交和错误捕获。
- 全局错误用
_error:如果是不需要绑定到特定字段的全局错误,比如服务器500错误,用_error作为键,redux-form会将其作为errorprops传递给组件。
内容的提问来源于stack exchange,提问作者Balessan
相关产品推荐
相关产品推荐

