Redux-toolkit: "Actions must be plain objects" error

Created on 15 Sep 2020  路  3Comments  路  Source: reduxjs/redux-toolkit

Recently I got this strange error

Uncaught (in promise) Error: Actions must be plain objects. Use custom middleware for async actions.
    at dispatch (redux.js:200)
    at index.ts:40
    at serializableStateInvariantMiddleware.ts:190
    at index.js:11
    at immutableStateInvariantMiddleware.ts:262
    at dispatch (redux.js:638)
    at _temp3 (createAsyncThunk.ts:447)
dispatch @ redux.js:200
(anonymous) @ index.ts:40
(anonymous) @ serializableStateInvariantMiddleware.ts:190
(anonymous) @ index.js:11
(anonymous) @ immutableStateInvariantMiddleware.ts:262
dispatch @ redux.js:638
_temp3 @ createAsyncThunk.ts:447
Promise.then (async)
(anonymous) @ createAsyncThunk.ts:433
(anonymous) @ createAsyncThunk.ts:396
(anonymous) @ index.js:8
(anonymous) @ immutableStateInvariantMiddleware.ts:262
(anonymous) @ redux.js:477
(anonymous) @ index.tsx:42
commitHookEffectList @ react-dom.development.js:22030
commitPassiveHookEffects @ react-dom.development.js:22064
callCallback @ react-dom.development.js:336
invokeGuardedCallbackDev @ react-dom.development.js:385
invokeGuardedCallback @ react-dom.development.js:440
flushPassiveEffectsImpl @ react-dom.development.js:25392
unstable_runWithPriority @ scheduler.development.js:697
runWithPriority$2 @ react-dom.development.js:12149
flushPassiveEffects @ react-dom.development.js:25361
(anonymous) @ react-dom.development.js:25240
workLoop @ scheduler.development.js:641
flushWork @ scheduler.development.js:596
performWorkUntilDeadline @ scheduler.development.js:203

It's strange because I already use "custom middleware" (thunk from toolkit)

Here's my store setup

const logoutOnJWTExpiration: Middleware = () => (
  next: ThunkDispatch<RootState, typeof api, AllActionsType>
) => action => {
  const errorId = action.error?.id || action.payload?.id;
  if (errorId === ErrorIDs.WRONG_AUTH_TOKEN) {
    next(logout());
  }
  return next(action);
};

export const store = configureStore({
  reducer: rootReducer,
  middleware: getDefaultMiddleware =>
    getDefaultMiddleware({
      thunk: { extraArgument: api }
    }).concat(logoutOnJWTExpiration),
  devTools: process.env.NODE_ENV === 'development'
});

I'm using "@reduxjs/toolkit": "1.4.0"

Thank you for great library by the way :)

--- UPD

By the way this is how logout action looks like

export function logout(): ThunkResult<void> {
  return dispatch => {
    Storage.removeToken();
    Storage.removeUsername();
    Storage.removeTeamID();
    dispatch({ type: AuthenticateActions.AUTH_LOGOUT });
  };
}

I think the problem appear after moving to toolkit

Most helpful comment

@usman786-ctrl in the case above, this would have been correct:

-const logoutOnJWTExpiration: Middleware = () => (
+const logoutOnJWTExpiration: Middleware = (api) => (
  next: ThunkDispatch<RootState, typeof api, AllActionsType>
) => action => {
  const errorId = action.error?.id || action.payload?.id;
  if (errorId === ErrorIDs.WRONG_AUTH_TOKEN) {
-    next(logout());
+    api.dispatch(logout());
  }
  return next(action);
};

All 3 comments

you are adding a new thunk to the pipeline after the thunk middleware has run. You need to dispatch the logout action, not next it.

@phryneas sorry sir unable to understand can you explain a little bit more

@usman786-ctrl in the case above, this would have been correct:

-const logoutOnJWTExpiration: Middleware = () => (
+const logoutOnJWTExpiration: Middleware = (api) => (
  next: ThunkDispatch<RootState, typeof api, AllActionsType>
) => action => {
  const errorId = action.error?.id || action.payload?.id;
  if (errorId === ErrorIDs.WRONG_AUTH_TOKEN) {
-    next(logout());
+    api.dispatch(logout());
  }
  return next(action);
};
Was this page helpful?
0 / 5 - 0 ratings