Search code examples
javascriptreactjsasynchronousreduxthunk

Redux-Thunk Error: Actions must be plain objects. Use custom middleware for async actions


I have a songbook app with firebase as a backend and struggling with an Error: Actions must be plain objects. Use custom middleware for async actions.

Action creator

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);

Solution

  • You have to return the result of calling createAction function in your action creator functions that is:

    return createAction(SONGS_ACTION_TYPES.FETCH_SONGS_START);
    

    instead of:

    createAction(SONGS_ACTION_TYPES.FETCH_SONGS_START);