DEV Community

Bithman
Bithman

Posted on

React Native - Actions must be plain objects

Hi everyone, I wrote this post because maybe someone could help me to understand what I missed in my code and my brain about this error:
"Error: Actions must be plain objects. Use custom middleware for async actions."

I found a lot of information about this error but I can't figure out the solution.

First of all, context:
I'm working with a react native app, I have redux and redux-thunk in my store, I need to do a async GET from a URL to obtain data and dispatch the action to my redux.

This is my store configuration with redux-thunk:

import {createStore, applyMiddleware,compose} from 'redux';
import Reducers from './reducers'
import thunk from 'redux-thunk'
import Reactotron from '../app/ReactotronConfig'

const middleware = applyMiddleware(thunk);
export default configureStore = () => {
    let store = createStore(Reducers,compose(middleware, Reactotron.createEnhancer()) );
    return store
}
Enter fullscreen mode Exit fullscreen mode

This is my first dispatch in my main app module:

.
.
dispatch(statusActions.initialLoading());
Enter fullscreen mode Exit fullscreen mode

In my actions I have this:

export const actionCreators = {

    initialLoading: () => async dispatch => {
        await authSetup();
        await dispatch(flowManagementActions.getEquipments());
    }

Enter fullscreen mode Exit fullscreen mode

In my flowManagementActions I have this:

getEquipments: () => async dispatch => {
        const eqList = await dispatch(actionCreators.getEquipmentList());
        let prom = [];
        eqList.map( eq => {       prom.push(dispatch(actionCreators.getEquipmentsWithActivity(eq)));
        });
        return Promise.all(prom);
      },

getEquipmentsWithActivity: (eq) =>  async (dispatch, getState) => {

        return dispatch(FlowManagementService.fetchEquipments(eq).then(
          (response) => {
            data = {...response.data,"id":eq.id};
             return dispatch(
                {
                  type: 'GET_EQUIPMENTS',
                  target: 'equipments',
                  payload: {...data,"model":eq.model,"id":eq.id},
                }
              )
            }
          )
        );
        }
Enter fullscreen mode Exit fullscreen mode

This is my FlowManagmentService

const testEndpoints = {
  fetchEquipments: (equipment) => 
  {
     return apiTest.get(`/equipments/${equipment.id}`)
  }
};

export default (testEndpoints);
Enter fullscreen mode Exit fullscreen mode

apiTest use apiSauce

export const apiTest = create({
  baseURL,
  timeout: API_TIMEOUT
});
Enter fullscreen mode Exit fullscreen mode

This is my reducer:

export default flowManagementReducer = (state = stateDescription, action) => {
    switch(action.type) {
        case "GET_EQUIPMENTS":
            {
              const newEquipments = state.equipments;
              newEquipments.push(action.payload);
              return {...state, equipments:newEquipments}
            }
        default:{
            return state
        }

    }
  }


Enter fullscreen mode Exit fullscreen mode

The final result it's ok, I have in my store the data, but I get this error:

Error: Actions must be plain objects. Use custom middleware for async actions.
dispatch@http://10.0.2.2:8081/index.bundle?platform=android&dev=true&minify=false:100221:24
http://10.0.2.2:8081/index.bundle?platform=android&dev=true&minify=false:134246:25
_callee2$@http://10.0.2.2:8081/index.bundle?platform=android&dev=true&minify=false:126398:59
tryCatch@http://10.0.2.2:8081/index.bundle?platform=android&dev=true&minify=false:24969:23
invoke@http://10.0.2.2:8081/index.bundle?platform=android&dev=true&minify=false:25142:32
tryCatch@http://10.0.2.2:8081/index.bundle?platform=android&dev=true&minify=false:24969:23
invoke@http://10.0.2.2:8081/index.bundle?platform=android&dev=true&minify=false:25042:30
http://10.0.2.2:8081/index.bundle?platform=android&dev=true&minify=false:25072:19
tryCallTwo@http://10.0.2.2:8081/index.bundle?platform=android&dev=true&minify=false:27095:9
doResolve@http://10.0.2.2:8081/index.bundle?platform=android&dev=true&minify=false:27259:25
Promise@http://10.0.2.2:8081/index.bundle?platform=android&dev=true&minify=false:27118:14
callInvokeWithMethodAndArg@http://10.0.2.2:8081/index.bundle?platform=android&dev=true&minify=false:25071:33
enqueue@http://10.0.2.2:8081/index.bundle?platform=android&dev=true&minify=false:25076:157
async@http://10.0.2.2:8081/index.bundle?platform=android&dev=true&minify=false:25093:69
_callee2@http://10.0.2.2:8081/index.bundle?platform=android&dev=true&minify=false:126394:42
http://10.0.2.2:8081/index.bundle?platform=android&dev=true&minify=false:126438:37
map@[native code]
_callee3$@http://10.0.2.2:8081/index.bundle?platform=android&dev=true&minify=false:126436:27
tryCatch@http://10.0.2.2:8081/index.bundle?platform=android&dev=true&minify=false:24969:23
invoke@http://10.0.2.2:8081/index.bundle?platform=android&dev=true&minify=false:25142:32
tryCatch@http://10.0.2.2:8081/index.bundle?platform=android&dev=true&minify=false:24969:23
invoke@http://10.0.2.2:8081/index.bundle?platform=android&dev=true&minify=false:25042:30
http://10.0.2.2:8081/index.bundle?platform=android&dev=true&minify=false:25052:21
tryCallOne@http://10.0.2.2:8081/index.bundle?platform=android&dev=true&minify=false:27086:16
http://10.0.2.2:8081/index.bundle?platform=android&dev=true&minify=false:27187:27
_callTimer@http://10.0.2.2:8081/index.bundle?platform=android&dev=true&minify=false:30626:17
_callImmediatesPass@http://10.0.2.2:8081/index.bundle?platform=android&dev=true&minify=false:30665:17
callImmediates@http://10.0.2.2:8081/index.bundle?platform=android&dev=true&minify=false:30882:33
__callImmediates@http://10.0.2.2:8081/index.bundle?platform=android&dev=true&minify=false:2736:35
http://10.0.2.2:8081/index.bundle?platform=android&dev=true&minify=false:2522:34
__guard@http://10.0.2.2:8081/index.bundle?platform=android&dev=true&minify=false:2719:15
flushedQueue@http://10.0.2.2:8081/index.bundle?platform=android&dev=true&minify=false:2521:21
flushedQueue@[native code]
Enter fullscreen mode Exit fullscreen mode

This are my dependecies in package.json

"dependencies": {
    "@react-native-async-storage/async-storage": "^1.13.2",
    "@react-native-community/masked-view": "^0.1.10",
    "@react-navigation/native": "^5.8.10",
    "@react-navigation/stack": "^5.12.8",
    "@reduxjs/toolkit": "^1.5.0",
    "apisauce": "^2.0.1",
    "react": "16.13.1",
    "react-native": "0.63.4",
    "react-native-config": "^1.4.1",
    "react-native-gesture-handler": "^1.9.0",
    "react-native-modal": "^11.6.1",
    "react-native-reanimated": "^1.13.2",
    "react-native-safe-area-context": "^3.1.9",
    "react-native-screens": "^2.16.1",
    "react-redux": "^7.2.2",
    "reactotron-apisauce": "^3.0.0",
    "reactotron-react-native": "^5.0.0",
    "reactotron-redux": "^3.1.3",
    "redux-logger": "^3.0.6",
    "redux-thunk": "^2.3.0",
    "reselect": "^4.0.0",
    "socket.io-client": "^3.0.5"
  }
Enter fullscreen mode Exit fullscreen mode

Maybe someone give me a clue and I can continue work on that path

Thanks a lot, sincerely I'm worked on it for a lot of time but I can't found a explanation.

Thanks in advance for the orientation.

Sorry for my english if I had a mistake but I gave my best effort to write in the best way.

Sentry image

See why 4M developers consider Sentry, “not bad.”

Fixing code doesn’t have to be the worst part of your day. Learn how Sentry can help.

Learn more

Top comments (0)

Billboard image

The Next Generation Developer Platform

Coherence is the first Platform-as-a-Service you can control. Unlike "black-box" platforms that are opinionated about the infra you can deploy, Coherence is powered by CNC, the open-source IaC framework, which offers limitless customization.

Learn more