react-redux-promise-listener仅含React Final Form示例,如何结合redux-form与redux-observable使用?
没问题,我来给你梳理一下怎么把这三个库结合起来用——核心思路就是用react-redux-promise-listener把redux-observable的异步流转换成组件里能直接用的Promise,再和redux-form的提交逻辑无缝对接。下面是一步步的具体实现:
1. 先配置Redux Store,整合依赖
首先得把react-redux-promise-listener的reducer和middleware加到你的Redux Store里,同时也要集成redux-observable的epic middleware和redux-form的reducer:
import { createStore, applyMiddleware, combineReducers } from 'redux'; import { createEpicMiddleware } from 'redux-observable'; import { reducer as formReducer } from 'redux-form'; import { createPromiseListener } from 'react-redux-promise-listener'; // 创建全局的promiseListener实例 export const promiseListener = createPromiseListener(); // 合并所有reducer const rootReducer = combineReducers({ form: formReducer, // redux-form的reducer promiseListener: promiseListener.reducer, // 必须加入这个reducer来追踪Promise状态 }); // 初始化redux-observable的middleware const epicMiddleware = createEpicMiddleware(); // 创建store,按顺序加入promiseListener的middleware和epic middleware const store = createStore( rootReducer, applyMiddleware(promiseListener.middleware, epicMiddleware) ); // 运行根epic(后面会定义) epicMiddleware.run(rootEpic); export default store;
2. 编写处理表单提交的Redux-Observable Epic
接下来写一个epic来监听表单提交的action,处理异步逻辑后,通过promiseListener通知组件Promise的结果:
import { ofType } from 'redux-observable'; import { mergeMap } from 'rxjs/operators'; import { promiseListener } from './store'; // 定义表单提交的action类型(要保证全局唯一) const SUBMIT_MY_FORM = 'SUBMIT_MY_FORM'; // action creator:触发表单提交的action export const submitMyForm = (formValues) => ({ type: SUBMIT_MY_FORM, payload: formValues, }); // 对应的epic:处理异步请求 export const submitMyFormEpic = (action$) => action$.pipe( ofType(SUBMIT_MY_FORM), mergeMap((action) => { // 这里替换成你的真实API请求,比如axios.post或者fetch return fetch('/api/submit-form', { method: 'POST', body: JSON.stringify(action.payload), headers: { 'Content-Type': 'application/json' }, }) .then((response) => { if (!response.ok) throw new Error('提交失败,请重试'); return response.json(); }) .then((apiResult) => { // 告诉promiseListener:这个action对应的Promise成功了 return promiseListener.resolve(SUBMIT_MY_FORM, apiResult); }) .catch((error) => { // 告诉promiseListener:这个action对应的Promise失败了 return promiseListener.reject(SUBMIT_MY_FORM, error); }); }) ); // 根epic,合并所有epic export const rootEpic = combineEpics(submitMyFormEpic);
3. 封装Redux-Form组件,集成Promise Listener
最后在你的表单组件里,用react-redux-promise-listener把提交逻辑转换成Promise,配合redux-form的handleSubmit使用:
import React from 'react'; import { Field, reduxForm } from 'redux-form'; import { connect } from 'react-redux'; import { promiseListener } from './store'; import { submitMyForm } from './epics'; const MyForm = ({ handleSubmit, listener }) => { const handleFormSubmit = async (formValues) => { try { // 创建Promise:第一个参数是action类型,第二个是要dispatch的提交action const submitResult = await listener.createPromise(SUBMIT_MY_FORM, submitMyForm(formValues)); // 提交成功后的逻辑,比如弹窗提示、跳转页面 alert(`提交成功!返回数据:${JSON.stringify(submitResult)}`); } catch (error) { // 提交失败后的逻辑,比如显示错误提示 alert(`提交失败:${error.message}`); } }; return ( <form onSubmit={handleSubmit(handleFormSubmit)}> <div> <label>用户名</label> <Field name="username" component="input" type="text" placeholder="请输入用户名" /> </div> <div> <label>邮箱</label> <Field name="email" component="input" type="email" placeholder="请输入邮箱" /> </div> <button type="submit">提交表单</button> </form> ); }; // 用reduxForm包裹表单,指定表单唯一标识 const ReduxWrappedForm = reduxForm({ form: 'myUniqueForm' })(MyForm); // 连接Redux,把promiseListener的实例注入组件 export default connect( null, null, // 用mergeProps把listener传入组件 (state, dispatch, ownProps) => ({ ...ownProps, listener: promiseListener.createListener({ dispatch }), }) )(ReduxWrappedForm);
关键注意点
- action类型必须一致:
createPromise的第一个参数、epic里监听的ofType参数、resolve/reject的第一个参数,必须是同一个action类型,否则promiseListener无法正确匹配Promise的状态。 - 不要跳过resolve/reject:epic处理完异步逻辑后,必须调用
promiseListener.resolve或reject,否则组件里的Promise会一直处于pending状态。 - redux-form的验证逻辑不受影响:redux-form自带的表单验证(比如required、自定义validator)会在
handleSubmit里自动执行,只有验证通过才会进入我们的handleFormSubmit函数。
内容的提问来源于stack exchange,提问作者FunctorPrototype
相关产品推荐
相关产品推荐

