1
votes

I'm using redux with redux-observable and get this strange error:

Actions must be plain objects. Use custom middleware for async >actions.

/* Component.jsx */
import React from "react"
import { serialNumberCheck } from '../actions'

const Component = props => {
  ...
  <button
    onClick={() => props.serialNumberCheck('123456789123456')}
  >
    Check
  </button>
  ...
}

const mapDispatchToProps = dispatch =>
  bindActionCreators({serialNumberCheck}, dispatch)

export default compose(
  reduxForm({
    ...
  }),
  withStyles(styles),
  connect(mapDispatchToProps)
)(Component)



/* actions.js */
export const SERIAL_NUMBER_CHECK = 'SERIAL_NUMBER_CHECK'
export const SERIAL_NUMBER_CHECK_SUCCESS = 'SERIAL_NUMBER_CHECK_SUCCESS'

export const serialNumberCheck = (serialNumber) => ({
  type: SERIAL_NUMBER_CHECK,
  payload: serialNumber
})

export const serialNumberCheckSuccess = (data) => ({
  type: SERIAL_NUMBER_CHECK,
  payload: data
})



/* epics.js */
...
import { serialNumberCheck } from "../actions"
import ... from 'rxjs'

...
function serialNumberCheckEpic(action$) {
  return action$
    .ofType(SERIAL_NUMBER_CHECK)
    .switchMap((data) => {
      return ajax.getJSON(`http://localhost:3004/sn/?sn=${data.payload}`)
      .map((data) => data)
    })
    .map(data => {
      if(data.length !== 0) {
        serialNumberCheckSuccess({success: true});
      }
    })
}

...
export const rootEpic = combineEpics(
  ...
  serialNumberCheckEpic
);



/* reducer.js */
import {
  SERIAL_NUMBER_CHECK_SUCCESS,
} from '../actions'

...
export default function epicReducer(state = initialState, action) {
  switch (action.type) {
    case SERIAL_NUMBER_CHECK_SUCCESS:
      return {
        ...state,
        success: action.payload
      }
  }
}

/* JSON-SERVER RESPONSE */
[
  {
    "id": 1,
    "sn": "123456789123456"
  }
]

Inside component i'am calling function serialNumberCheck() and passing inside sierial number that we need to check.

Inside Epic im passing serial number to json-server that checks if this number exists in my "database". If serial number exists, server response is .json containing some parameters.

So if response isn't empty we need to write success: true inside redux store.

But in the end we get successfull GET request, and then error: Actions must be plain objects. Use custom middleware for async actions., but no changes inside redux-store and nothing from SERIAL_NUMBER_CHECK_SUCCESS action.

1
The first argument in connect should be mapStateToProps or null if you don't have one - the second argument is mapDispatchToPropslux
@lux, mapStateToProps is thereРинат Москвин

1 Answers

1
votes

Finally, I found the solution. I've just missed the return before calling action inside my epic.

function serialNumberCheckEpic(action$) {
  return action$
    .ofType(SERIAL_NUMBER_CHECK)
    .switchMap((data) => {
      return ajax.getJSON(`http://localhost:3004/sn/?sn=${data.payload}`)
      .map((data) => data)
    })
    .map(data => {
      if(data.length !== 0) {
        + return serialNumberCheckSuccess({success: true});
      }
    })
}