Redux-Thunk触发Actions must be plain objects报错排查
Redux异步Action触发
Actions must be plain objects报错排查 问题场景
开发基于Firebase作为后端的歌本应用时,调用异步Action触发如下报错:
Error: Actions must be plain objects. Use custom middleware for async actions
已按照文档配置redux-thunk中间件,相关代码如下:
基础Action构造函数
export const createAction = (type, payload) => ({ type, payload });
songs.action.js
import { getSongsAndDocuments } from '../../utils/firebase/firebase.utils'; export const fetchSongsStart = () => { createAction(SONGS_ACTION_TYPES.FETCH_SONGS_START); }; export const fetchSongsSuccess = songs => { createAction(SONGS_ACTION_TYPES.FETCH_SONGS_SUCCESS, songs) }; export const fetchSongsFailed = error => { createAction(SONGS_ACTION_TYPES.FETCH_SONGS_FAILED, error); }; export const fetchSongsAsync = () => { return async dispatch => { dispatch(fetchSongsStart()); try { const songs = await getSongsAndDocuments(); dispatch(fetchSongsSuccess(songs)); } catch (error) { dispatch(fetchSongsFailed(error)); } }; };
Songbook.jsx 调用逻辑
const dispatch = useDispatch(); useEffect(() => { dispatch(fetchSongsAsync()); }, []);
store.js 配置
import { compose, createStore, applyMiddleware } from 'redux'; import thunk from 'redux-thunk'; import { rootReducer } from './root-reducer'; const middleWares = [thunk]; const composeEnhancer = (process.env.NODE_ENV !== 'production' && window && window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__) || compose; const composedEnhancers = composeEnhancer(applyMiddleware(...middleWares)); export const store = createStore(rootReducer, undefined, composedEnhancers);
问题根因
redux-thunk中间件配置没有问题,报错来自同步Action创建函数的写法错误:
三个同步Action创建函数fetchSongsStart、fetchSongsSuccess、fetchSongsFailed的函数体内仅调用了createAction,但没有返回生成的action对象,函数默认返回undefined。
当thunk异步逻辑执行dispatch(fetchSongsStart())时,实际传入dispatch的是undefined,不符合Redux要求「Action必须是普通对象」的规则,因此触发报错。
修复方案
修改三个同步Action创建函数,返回生成的action对象即可,两种写法均可:
- 显式return写法
export const fetchSongsStart = () => { return createAction(SONGS_ACTION_TYPES.FETCH_SONGS_START); }; export const fetchSongsSuccess = songs => { return createAction(SONGS_ACTION_TYPES.FETCH_SONGS_SUCCESS, songs) }; export const fetchSongsFailed = error => { return createAction(SONGS_ACTION_TYPES.FETCH_SONGS_FAILED, error); };
- 箭头函数隐式返回写法(更简洁)
export const fetchSongsStart = () => createAction(SONGS_ACTION_TYPES.FETCH_SONGS_START); export const fetchSongsSuccess = songs => createAction(SONGS_ACTION_TYPES.FETCH_SONGS_SUCCESS, songs); export const fetchSongsFailed = error => createAction(SONGS_ACTION_TYPES.FETCH_SONGS_FAILED, error);
修改完成后重新运行项目,异步拉取歌曲列表的逻辑即可正常执行。
内容的提问来源于stack exchange,提问作者Tom Foxtrot
相关产品推荐
相关产品推荐

