Search code examples
javascriptreduxreact-reduxredux-thunkredux-middleware

Redux: Proper way to access state from web service?


I have outlined a few ways to possibly access state from the web service, but I do not know which one is the proper one in a react-redux app, or if the proper one is even listed below.

Context:

Originally, I had an API.js file which acted as a base for web services. I would then import this into my action files. This went well until I needed to access the state (more specifically, a web token in the state that I needed for my header) from API.js. I tried to import my store, but it returned undefined. I then realized I had a circular dependency:

api -> store -> reducers -> components -> actions

Custom Middleware


I was wondering if this is acceptable. I ditched my API.js. I use this to automatically modify outgoing network calls that have a specific action type. This is what my middleware stack looks like:

const middleware = applyMiddleware(
    myCustomModifyRequestMiddleware,
    thunk,
    . . .

And myCustomModifyRequestMiddleware basically looks like:

 const myCustomModifyRequestMiddleware = store => next => action {
     if(action.type === 'MODIFY_ME') {

         //Dispatch an FSA
         store.dispatch({
             type: action.payload.actual_type,
             payload: axios.create({ . . .
             meta: action.meta
         })
     }

     return next(action)
 }

Now I have business logic inside my middleware!

Then I could just have an action creator named API_ActionCreator. But hey, if I was just going to use an action creator why not just...

Thunk it


Using thunks I could probably just have something like API_ActionCreator.js:

const apiActionCreator = (actual_type, url, data . . .) {
    return (dispatch, store) {
        //Now I can get the state...
        store.getState()

        //Return an FSA
        return { 
            type: actual_type,
            payload: axios.create...

Now I can import my API_ActionCreator into my actions without any circular dependencies.

Subscribing to the store ?

Another way would be to have the web service be stateful; subscribe to the store in store or the web service, if I could somehow avoid running into a circular dependency when I called my web services inside my actions.

TLDR; Of course, this is all experimental, though I was able to get the middleware working.

I don't know which one is the most viable approach, is there maybe a more redux-ish way to do this?


Solution

  • Thunk action creators and centralized middleware are both standard approaches for managing API calls in Redux while having access to dispatch and getState`. Either of those is fine.

    For more info, see Dan's answers on managing async behavior in Redux and why thunks and other middleware are useful for async work, as well as the other articles in the Redux Side Effects section of my React/Redux links list. You might also be interested in the list of Redux middleware for making network requests in my Redux addons catalog.