title: React, Immutable, fetch() - incorrect error handling leading to undefined state element?
body: <p>I think I understand <em>where</em> the error is occurring but I am able to work out the correct handling flow for a <strong>Promise</strong> returned from <strong>fetch()</strong></p>
  
  <p>My Messages reducer module: -</p>
  
  <pre><code>import { fetchMessages } from '_helpers/api'
  import { Map, fromJS } from 'immutable'
  
  const FETCHING_MESSAGES = 'FETCHING_MESSAGES'
  const FETCHING_MESSAGES_FAILURE = 'FETCHING_MESSAGES_FAILURE'
  const FETCHING_MESSAGES_SUCCESS = 'FETCHING_MESSAGES_SUCCESS'
  const ADD_MESSAGES = 'ADD_MESSAGES'
  
  const ERROR_MESSAGE = 'There has been an error'
  
  export const fetchAndHandleMessages = () =&gt; {
  
    return (dispatch, getState) =&gt; {
  
      dispatch(fetchingMessages())
  
      fetchMessages()
        .then((r) =&gt; {
          if (!r.ok) {
            dispatch(fetchingMessagesFailure(ERROR_MESSAGE))
          }else{
            return r.json()
          }
        })
        .then((b) =&gt; {
          dispatch(fetchingMessagesSuccess(b))
        })
        .catch(() =&gt; {
          dispatch(fetchingMessagesFailure(ERROR_MESSAGE))
        })
    }
  }
  
  function fetchingMessagesSuccess(messages) {
    return {
      type: FETCHING_MESSAGES_SUCCESS,
      messages,
      lastUpdated: Date.now(),
    }
  }
  
  function fetchingMessagesFailure(errMsg) {
    return {
      type: FETCHING_MESSAGES_FAILURE,
      error: errMsg
    }
  }
  
  const fetchingMessages = () =&gt; {
    return {
      type: FETCHING_MESSAGES,
    }
  }
  
  const initialState = fromJS({
    messages: [],
    isFetching: true,
    error: '',
  })
  
  export const messagesReducer = (state = initialState, action) =&gt; {
    switch (action.type) {
      case FETCHING_MESSAGES :
        return state.merge({
          isFetching: true,
        })
      case FETCHING_MESSAGES_SUCCESS :
        return state.merge({
          error: '',
          isFetching: false,
          messages: action.messages
        })
      case FETCHING_MESSAGES_FAILURE:
        return state.merge({
          error: action.error,
          isFetching: false
        })
      default :
        return state
    }
  }
  
  export default messagesReducer
  </code></pre>
  
  <p>fetchMessages() simply returns a promise: -</p>
  
  <pre><code>export const fetchMessages = () =&gt; {
    return fetch(baseUrl + 'messages')
  }
  </code></pre>
  
  <p>I am not going to post the component code here because it is not relevant to the issue.</p>
  
  <p>So if I call fetchMessages() with an invalid URL to return a 404, state.messages becomes <strong>undefined</strong> in my component. This would seem to be being caused by this part of the function: -</p>
  
  <pre><code>        if (!r.ok) {
            dispatch(fetchingMessagesFailure(ERROR_MESSAGE))
          }else{
            return r.json()
          }
  </code></pre>
  
  <p>I think I might be confused regarding how to properly check and deal with potential errors in the returned Promise. According to the docs for fetch(), a 404 is not considered to be an error as (unlike regular AJAX) only network issues are considered to be a catch() type of error.</p>
  
  <p>Can anyone pinpoint for me what is wrong with this part of my code? should I be using <strong>exit</strong> after <strong>dispatch(fetchingMessagesFailure(ERROR_MESSAGE))</strong> to stop the following <strong>.then()</strong>? Also, even with just a 404, the <strong>.catch()</strong> block is also being run. This seems to be against what the docs suggest.</p>
  
  <p>Any help greatly appreciated. Thanks.</p>