0

I'm writing a React (actually, React Native) application that stores data locally and submits it to a backend for processing. More specifically, it allows a user to place orders for products, and if submission fails because, e.g., the user is not currently logged in, the data must be stored and re-submitted to the backend later.

The application is built using a Flux data flow. I've read a lot about Flux but I still cannot understand how to handle this case:

  1. User places an order: a React component calls an Action Creator method and passes in the order data
  2. The Action Creator submits the order asynchronously to the backend
  3. The order submission fails (e.g., because the user hasn't logged in yet)
  4. The error is fixed (e.g., the user logs in)
  5. The data has to be automatically resubmitted to the backend

Where does the data live between steps #3-5? I can think of two possible ways to handle this but I'm not sure which, if either, is correct according to Flux. Here's the first:

  1. The Action Creator creates an ORDER_SUBMIT_FAILED action and attaches the order data to it.
  2. The Order Store receives the action and stores the order in a "pending orders" list.
  3. The user logs in, and a LOGIN_SUCCESS action is generated.
  4. The Order Store receives this action, too, and re-submits the "pending orders".

But I don't understand how the Order Store can re-submit data to the network. Per Should flux stores, or actions (or both) touch external services?, my Stores are dumb data repositories and all network activities happen in the Action Creators. Should the Store pass the data back to the Action Creator? But this seems to violate Flux.

The other is:

  1. The Action Creator loads the login screen and passes it a callback.
  2. The login screen handles the login process, and when it's done successfully, calls the callback.
  3. The callback (into the Action Creator) allows it to re-submit the failed orders.

But using callbacks also doesn't seem terribly flux-like.

React/Flux way to handle permission sensitive actions with login flows discusses a similar situation but focuses on how to check for a login in the first place. The accepted answers suggests following the first proposed flow above but doesn't answer the question I posed there.

Thanks!

Community
  • 1
  • 1
Lane Rettig
  • 6,640
  • 5
  • 42
  • 51

2 Answers2

0

Here is the way I'm dealing with that problem. Not sure if it's following any recommendations, but for me it works quite nicely.

The ORDER_SUBMIT action is pick up only by the local OrderStore at first. There it's saved locally in a pending state. From there it's send to the backend with a second, async action. I actually have a sync process that collects potentially multiple updates on different store and sends them all at once to a single "sync" endpoint. But just the straight forward async action you currently use works fine as well. When the sync action returns it updates the local store with the server data. Depending how you implement the sync you might need to generate a local ID that get's sent to the server and back in order to match the server result to you local dataset. If the backend call fails you set your local dataset into a state the indicates it needs to be resend. And then you can at opportune moments check your stores for items the need to be re-send and just generate the appropriate sync actions again. As I said, I'm not sure if this is best practice, but for me it works.

d-vine
  • 5,317
  • 3
  • 27
  • 25
  • Re: "From there it's send to the backend with a second, async action": in my case I prefer the Store not know anything about the backend. This isn't a hard and fast rule but it's how I prefer to do it. (You can read more about why at http://stackoverflow.com/questions/25630611/should-flux-stores-or-actions-or-both-touch-external-services/25648726#25648726.) Also, re: "And then you can ... check your stores for items the need to be re-send and just generate the appropriate sync actions again", where does this happen? Thanks! – Lane Rettig Jan 21 '16 at 18:14
  • I'm actually using Reflux that approaches things more from smart store / dumb action perspective. I'm a bit unsure about the cascading Actions, but didn't find a better way to do it, yet. Call functions directly on the Stores can lead to a total dependency mess. The checking for open re-submits would again be happening in the stores listening for a "reconnect" or whatever action and issuing sync actions. – d-vine Jan 21 '16 at 20:01
0

In my own flux variant (somewhat like redux), I don't have action creators, instead all actions are just dispatched payloads - no asynchronous actions. Instead, I have plain JS classes (called asynchronous handlers) that bind to store state (via a 'getter' function), just like React components do. So if I want to trigger a data save, I have a store set some state to indicate that a save should occur, then the handler sees the change and makes the request, dispatching actions as desired for success, etc. Handlers are created at start up.

In your case, an asynchronous handler could Bind to pending orders and the login status and act accordingly as the stores update them.

TomW
  • 3,923
  • 1
  • 23
  • 26