I am building a site with React and Redux and I have a query about how I should be handling 401 status responses.
Currently when the API reports a 401 HTTP Status it is usually caught in one of my actions and I dispatch:
You said :
And the related reducer checks the HTTP status code...
Using a middleware is great but the reducer should not check for the http status. It would be outside of its purpose.
From the documentation :
The reducer job is to specify how the application's state changes in response.
Your action-creators should be pure, all the async codes should live somewhere else.
Side effects do not belong in reducers
There are many ways to do it. It all comes down to preferences.
Here are 3 ways to handle HTTP requests in a more elegant way:
Option 1 (the most powerful one) : Generators, Sagas and complex chains of asynchronous operations
redux-saga allows you to do just that. I personally use this middleware to handle my api calls and responses.
The mental model is that a saga is like a separate thread in your application that's solely responsible for side effects. redux-saga is a redux middleware, which means this thread can be started, paused and cancelled from the main application with normal redux actions, it has access to the full redux application state and it can dispatch redux actions as well.
Here are the benefits I get from using this option :
Simplify implementation of use cases like:
In a large multi-user, multi-department blog, if a user had ever clicked on a "subscribe to RSS Feed" button, then the next time the user visits a section that has a dedicated RSS feed, show him/her a suggestion to subscribe to this section's feed.
In an online IDE, if a user has never used a particular feature of an application, but has arrived at a state that the aforementioned feature might potentially be useful, show a help dialog introducing this feature.
In stackoverflow, while the user was responding to a question, the question has been changed by OP so you inform the user that the question has been changed and the answer is potentially no longer valid.
So far so good. We removed the coupling, separated our the async logic somewhere else and have a clean architecture. However, redux-saga's more advanced feature will simplify complex use cases.
Here is the gist of redux thunk :
Asynchronous middleware like redux-thunk or redux-promise wraps the store's dispatch() method and allows you to dispatch something other than actions, for example, functions or Promises. Any middleware you use can then interpret anything you dispatch, and in turn, can pass actions to the next middleware in the chain. For example, a Promise middleware can intercept Promises and dispatch a pair of begin/end actions asynchronously in response to each Promise.
Option 3 : Managing side effects through Higher order components
Exemple : axios, a promise based HTTP client for the browser and node.js
Option 4 : Generators and promises, sans Sagas
Last but not the least, you can still use generators to manage your async control flow, in frontend, without adding redux-thunk dependency, if you do not need some of its advanced features.