redux-utilities/redux-actions

Error handling on action payload

sombreroEnPuntas opened this issue · 2 comments

I'm following the docs to implement redux-actions in a project.
https://redux-actions.js.org/api/createaction#createactiontype

When I get to the error handling example:

const noop = createAction('NOOP');

const error = new TypeError('not a number');
expect(noop(error)).to.deep.equal({
  type: 'NOOP',
  payload: error,
  error: true
});

I noticed that when I pass an error for testing, like this:

const {
  successAction,
  errorAction
} = createActions({
  SUCCEESS_ACTION: payload => ({
    data: payload
  }),
  ERROR_ACTION: payload => ({
    error: payload
  }),
});

  try {
    let data;
    // ... some stuff to fetch data :)

    throw Error('Bad times on the internetz');

    successAction(data);
  } catch (error) {
    errorAction(error):
  }

The action is now:

{
  type: 'ERROR_ACTION',
  payload: {}, // Expected it to be 'Error: Bad times on the internetz' instance
  error: true
}

Did I write a wrong implementation? What should be the right way to get the error?
I want to be able to reduce the action with an error payload and save the error to the store for further steps (like showing a toast with the error message to the user)

:(

Flux Standard Actions, which redux-actions providers helpers for, represent success and error "versions" of an action as the same action type. createAction() will create action-creator functions which accept either a value or an error object. When the code which may have success or error paths needs to dispatch an action, you can use the same action creator.

// action creators.js
const readDataCompleted = createAction('DATA/READ_COMPLETED`)

// getdata.js
import somethingHappened from './actions'
import store from './store'

try {
  const response = await fetch('some_url')
  
  if(!response.ok) throw new Error('Bad times on the internetz.')

  const body = await response.json()
  store.dispatch(somethingHappened(body))
}
catch (err) {
  store.dispatch(somethingHappened(err))
}

Code similar to this will produce a "success" action when following the happy path:

{
  type: 'DATA/READ_COMPLETED',
  payload: /* ... your data ... */
}

... and an 'error' action when following the error path:

{
  type: 'DATA/READ_COMPLETED',
  error: { message: 'Bad times on the internetz.' }
}
// well, it'll be a proper error object, not the pseudo-error object I wrote above.

This means that your reducers need to contain logic for handling the success and error states. You can roll your own, or use handleAction()/handleActions(), also included in the redux-actions library, to help create these "error aware" reducers. I'll leave you to look at the docs for handleAction().