You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 15:27:17