0
votes

I am trying to handle API error using Redux dispatch, by creating action, reducer & connect(mapStateToProps) at the end.

So when I enter wrong url, I get error message on my view. But my button links wrapped inside tag are clicked then my next view shows a same the error message instead on rendering the new view.

// Actions
export const API_ERROR = "API_ERROR"
export const resetErrorCode = () => ({
  type: RESET_ERROR_CODE
})

// Reducers
import { API_ERROR, RESET_ERROR_CODE } from "actions"

const api = (state = { errorCode: null }, action) => {
  switch (action.type) {
    case API_ERROR:
      return { ...state, errorCode: action.errorCode }

    case RESET_ERROR_CODE:
      return { ...state, errorCode: action.errorCode }

    default:
      return { errorCode: null }
  }
}
export default api

// Combiner reducers
import { combineReducers } from 'redux'
import API from "./api"

export default combineReducers({
  API
});

// test.jsx
import { connect } from 'react-redux'
import API from 'api.js'
import { resetErrorCode } from 'actions'
import { Link } from 'react-router-dom'
class Test extends Component {
    componentDidMount() {
       API.call()
     }
  render() {
    switch (this.props.errorCode) {
      case 400:
      case 404:
        return (
          <div>
            Error Page
          </div>
        )
      default:
        return (
          <div>
            <Link to={{pathname: '/nextPage'}}> <button> Next Page </button> </Link>
          </div>
        )
    }
  }

   componentWillUnmount() {
     this.props.errorCode()
  }
}

const mapStateToProps = (state) => {
  return {
    errorCode: state.apiStatus.errorCode,
  }
}

const mapDispatchToProps = (dispatch) => {
  return {
    errorCode: () => dispatch(resetErrorCode())
  }
}

export default connect(mapStateToProps)(Test)

// api.js
class API () {
   responseErrorHandler(statusCode) {
    console.log('responseErrorHandler() called')
    store.dispatch(notifyAPIError(statusCode))
  }
  call = () => {
     axios.get(url)
        .then(...)
        .catch((error) => this.responseErrorHandler(error.response.status))
     }
}

I monitored my redux state while correct url redux state shows {errorCode: null} and when I enter wrong url redux state changes to {erroCode: 404}. Now If click my button, new view is rendered but the error code dont changes. Redux state is still {erroCode: 404}.

I tried to use componentWillUnmount to change the status of errorCode to null but it's not working.

Is there any solution to this problem and I'm not sure about my approach of componentWillUnmount().

I would appreciate the help.

1

1 Answers

0
votes

I don't see much value on having the error on the Redux store if you're using it only inside a single component, and clearing it on unmount: a simple state would make things easier on this case.

If you're sure you want to go on that route, the right moment to clear the previous error is just when a new request is made, which happens on mounting of the component. This means that call() should reset the error before making the new call (which is now "loading"), and only set it again after it ends in an error.

Clearing at unmount would probably not be needed, as only pages which make the call need to check if an error happened, and those will reset it on mount.

Finally, some code bugs you might have:

  • Make sure your reducer is right: you don't usually modify the state on the "default" of the switch, as any other actions from other components would cause the state to get lost.
  • You're using the same prop name for the mapStateToProps and mapDispatchToProps, which is a problem. It doesn't fail because you're not using the mapDispatchToProps function on connect, so you might want to remove it entirely.