2

I'm migrating a project management app from angularjs to reactjs.

In the angularjs app I wait for promises to resolve when a route loads before showing it. All of the promises and their states are stored in a service that makes api calls. Some api calls need to wait for specific pending api calls so I get the most recent data.

For example: If the user adds a new project he is pushed to the project list route automatically. At the project list route an api call is made to fetch the list of projects, this api call waits for the add new project to succeed before calling for the list. If we didn't wait for the new project to finish being added, then we would have an old project list without the new project.

How does this translate to react/redux?

In redux I basically need an action that when dispatched will make sure to wait on any required pending actions before fetching data from the api. It's not the same as chaining async actions or calling a couple and waiting for both to resolve because in those instances you are saying "Call these actions." I need something that says "Call this action, but wait for any previously called dependencies to resolve first". I understand that you can store an isFetching flag or something similar in redux state, but then you'd have to watch those values and I'm not sure how to do that.

Two solutions I came across are redux middlewares: redux-wait-for-action and redux-when. They basically keep a list of actions that have been dispatched but are waiting on some other action types to be resolved. They check all actions to see if one of the ones on the list has been resolved, and if they find one then they dispatch the action that was waiting.

My questions are as follows:

  1. Is this flow, some route api calls waiting on pending api calls (possibly from previous routes) okay, or is there a better way of structuring my app so I don't depend on grouped resolves?

  2. Are redux actions that possibly need to wait on previously dispatched actions to resolve an antipattern or bad practice? I don't see many other people running into the same problem I am, which might be an indication I am doing something in a funny way.

  3. If everything is fine for my structure are there any problems with writing my own middleware that keeps track of waiting actions and dispatches them when they are ready? The reason I ask is neither of the two middlewares keep the waiting action list in the redux store, so technically the app state would be oblivious to this list. I don't want to cause problems later by having something out of the store, when it could be in the store.

Any and all input is appreciated, thanks guys!

Zack Knopp
  • 2,765
  • 2
  • 13
  • 14
  • If not a duplicate, this is very closely related: https://stackoverflow.com/a/35415559/497418 – zzzzBov Jun 05 '18 at 14:44
  • @zzzzBov Closely related, but not the same. That one is "Call this action after x seconds" whereas mine is "When calling a new action, check to make sure specific pending actions have been resolved" – Zack Knopp Jun 05 '18 at 14:53
  • Both of those scenarios are asynchronous action dispatching. Regardless, there's a reason I didn't use my dupe-hammer on this one. – zzzzBov Jun 05 '18 at 15:00

2 Answers2

1

I got help on a react/redux discord channel and came up with this:

  1. You should wait for the api call to resolve before pushing a route change. This way you don't have to keep track of any pending calls.
  2. Look above, it's not necessarily an anti-pattern, it's not a typical thing to do, but you can do it if you want, the extra complexity might not be worth the result. If you change routes before the api call is resolved then you get a race condition.
  3. The best way to do it would be to model your middleware after the other two you mentioned and track the pending actions in the store so your store has a complete picture of your application state.
Zack Knopp
  • 2,765
  • 2
  • 13
  • 14
1

if your using promise like axios and I suggest to use redux thunk

export const toDispatch = () =>{
  return dispatch =>{
    axios.get(url).then(()=>{
     dispatch(functionToDispatch())
    })
  }
}
jadlmir
  • 465
  • 1
  • 6
  • 16
  • That's just chaining an action to be dispatched after a promise resolves. What I wanted was for a new action to check for any dependant actions in progress before the new action fired, regardless of where or when they were called. :) – Zack Knopp Jun 05 '18 at 15:16