Redux多异步Reducer报错:已装thunk仍提示Action非纯对象
首先明确回答你的疑问:一个Redux应用完全可以有多个处理异步相关逻辑的reducer(准确来说,reducer本身都是同步纯函数,异步逻辑是通过thunk这类middleware在action层面处理的,多个reducer分别处理不同异步请求返回的状态更新是完全合法且常见的做法)。你的报错和多个reducer无关,是代码中的几个细节错误导致的,下面逐一说明并修正:
1. addtest Action 创建函数未返回合法的Plain Object Action
你的addtest函数使用了带大括号的箭头函数,但没有写return语句,导致它执行后返回undefined,而不是Redux要求的plain object类型的action,这直接触发了报错。
修正方法:
可以选择两种写法之一:
- 加上
return语句 - 去掉大括号,使用箭头函数的简洁写法(自动返回表达式结果)
修正后的addtest:
export const addtest=(tests)=> ({ type: 'ADD_TEST_UNIT', tests })
2. Fetch响应未解析为JSON数据
在saveTests的fetch回调中,你直接尝试访问testData.tests,但fetch API返回的是一个Response对象,不是后端返回的JSON数据,必须先调用.json()方法解析响应体。
修正后的saveTests:
export const saveTests = (testData = {}) => { return dispatch =>{ const { t_id=0, test_name= '', print_name= '', department= '', test_individual= 0, std_rate= '', prt_tst_np= 0, discon_prcls=0, unit= '', res_lst= 0, num_rng= 0, wrd_tempt= 0, tst_mthd= '', interpret= '', for_bsd_tst= 0, } = testData const tests = {t_id, test_name, print_name, department, test_individual, std_rate, prt_tst_np, discon_prcls, unit, res_lst, num_rng, wrd_tempt, tst_mthd, interpret, for_bsd_tst} return fetch('http://localhost/aruna/addtestunits.php',{ method:'POST', body: JSON.stringify(testData) }) .then(response => response.json()) // 新增:解析响应为JSON .then(data => dispatch(addtest(data.tests)) ) } }
3. Reducer中引用的Action属性名不匹配
你的test reducer中尝试访问action.testunit,但addtest action中传递的属性是tests,这会导致即使action正确触发,reducer也无法正确更新状态。
修正后的Reducer:
const testsDefaultstate = [] export default (state=testsDefaultstate, action ) => { switch (action.type){ case 'ADD_TEST_UNIT': return [ ...state, action.tests // 改为action.tests,和addtest中的属性名一致 ] default: return state } }
额外说明
你的Form组件中调用this.props.saveTests(...).then(...)的写法是没问题的,因为redux-thunk会让异步action creator返回一个Promise,只要你的fetch链正确传递Promise,这个then就能正常执行。
修正以上三个问题后,你的异步action应该就能正常触发,不会再出现那个报错了。
内容的提问来源于stack exchange,提问作者Akshay Sharma

