React Native+Redux-Thunk报错:Actions must be plain objects 求解决
嘿,我太懂这个报错的痛苦了!当初我第一次用Redux-Thunk结合Firebase的时候也踩过这个坑。这个错误本质是Redux默认只能处理普通对象类型的action,但你写的异步action是返回一个函数(这是Thunk的特性),如果你的Store没有正确配置Thunk中间件,Redux就会懵圈,直接给你抛这个错。
结合你给出的代码片段,我帮你梳理下最可能的问题和修复步骤:
1. 先检查Store的配置是否正确
你已经导入了thunk,但大概率是在创建Store的时候,没把Thunk中间件正确传入增强器里。看你的代码里有composeEnhancers的判断(应该是为了兼容Redux DevTools),正确的写法应该是这样:
import { createStore, combineReducers, compose, applyMiddleware } from 'redux'; import thunk from 'redux-thunk' import PlacesReducer from './placesReducer' const rootReducer = combineReducers({ places : PlacesReducer, }); // 正确配置DevTools增强器和Thunk中间件 let composeEnhancers = compose; if (__DEV__) { // 优先用DevTools的compose,没有的话用默认compose composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose; } // 关键:把applyMiddleware(thunk)放进composeEnhancers里 const store = createStore( rootReducer, composeEnhancers(applyMiddleware(thunk)) ); export default store;
很多人会犯的错是直接把applyMiddleware(thunk)单独传给createStore,而没和DevTools的增强器结合,这样就会导致Thunk中间件没生效。
2. 确认你的异步Action Creator写法正确
你的Action Creator必须返回一个接收dispatch参数的函数,而不是直接返回Firebase的异步操作。比如正确的提交Firebase数据的Action应该是这样:
// 假设这是你的actions/placesActions.js import firebase from 'firebase'; export const addPlace = (placeData) => { // 返回一个函数,Thunk会自动注入dispatch return (dispatch) => { // 执行Firebase的异步提交 firebase.database().ref('places') .push(placeData) .then(() => { // 异步操作成功后,dispatch一个普通对象类型的action给reducer dispatch({ type: 'ADD_PLACE_SUCCESS', payload: placeData }); }) .catch(error => { // 处理错误,也可以dispatch一个错误action dispatch({ type: 'ADD_PLACE_FAILED', payload: error.message }); }); }; };
千万别写成直接返回Promise或者async函数,必须是返回一个接收dispatch的函数,这是Thunk能识别的格式。
3. 在组件中正确触发Action
最后,确保你在组件里是通过dispatch来调用这个Action Creator的,而不是直接调用函数。比如用connect把dispatch映射到组件props:
import { connect } from 'react-redux'; import { addPlace } from '../actions/placesActions'; class YourComponent extends React.Component { // 比如在某个提交按钮的点击事件里 handleSubmit = () => { const placeData = { /* 你的数据 */ }; // 用props里的dispatch触发action this.props.addPlace(placeData); }; // ...其他组件代码 } export default connect(null, { addPlace })(YourComponent);
如果直接调用addPlace(placeData)而不通过dispatch,那这个函数只会返回一个函数,根本不会被Thunk处理,自然就会报错。
按照这几步检查下来,应该就能解决这个问题了!
内容的提问来源于stack exchange,提问作者Ahmed Mahmud

