redux-thunk and handling exceptions inside dispatch results

Viewed 23977

I have a basic thunk action creator and reducer adapted from the Redux documentation: http://redux.js.org/docs/advanced/AsyncActions.html

// action creator

function fetchPosts () {
  return dispatch => {
    dispatch({ type: 'FETCH_POSTS_REQUEST' })

    return fetch('http://jsonplaceholder.typicode.com/posts')
      .then(response => response.json())
      .then(json => dispatch({ type: 'FETCH_POSTS_SUCCESS', items: json }))
      // THIS CATCHES FETCH REQUEST ERRORS, AND COMPONENT LEVEL ERRORS
      .catch(error => dispatch({ type: 'FETCH_POSTS_FAILURE', error: error.message }))
  }
}

// reducer

function reducer (state = { isFetching: false, items: [] }, action) {
  switch (action.type) {
    case 'FETCH_POSTS_REQUEST':
      return Object.assign({}, state, { isFetching: true })
    case 'FETCH_POSTS_SUCCESS':
      return Object.assign({}, state, { isFetching: false, items: action.items })
    case 'FETCH_POSTS_FAILURE':
      return Object.assign({}, state, { isFetching: false })
    default:
      return state
  }
}

In a React component that is passed the state as props, I check for the presence of post items, and if present force an component level error:

const Test = props => {
  if (!props.items.length) return null
  throw new Error('Error!')
}

When starting the app:

  1. fetchPosts action creator is called
  2. A HTTP request is made, and after the response a FETCH_POSTS_SUCCESS action is dispatched.
  3. The component now updates with the resulting items in the state and attempts to read props.invalidProperty.error
  4. This causes a JS exception: Cannot read property 'error' of undefined

So far so good.

The issue is that the JS exception from the component is never output to the console. Instead, the catch() block for the fetch promise catches the error, and dispatches an FETCH_POSTS_FAILURE action.

This has the effect of swallowing all errors in components that were affected by updating the store. A FETCH_POSTS_FAILURE state change is dispatched, but this feels incorrect - there was no error actually fetching the posts, but an error downstream in a component using those posts.

I'm looking for a pattern to help separate errors in the async request from any other random error that occurs as a result of changing the state via dispatch.


EDIT:

Example with the async example in the Redux github repo: https://github.com/nandastone/redux/commit/88ab48040ce41c39d8daba8cc0c13a6f32c38adf#diff-eeb827d44ad03655e63b7e9319a03dd4R6

3 Answers
Related