Persistence of computed state with Redux

In my Meteor-React-Redux application, I have a sort of invoice that a user can add items to and change quantities, prices, descriptions, etc.

When a user adds or updates an item to the invoice, an action is created as a redux-thunk. The thunk is simple, it just updates the document in MongoDB corresponding to the invoice with the changes to the item. Then an action is dispatched for the reducer to note the change.

In the reducer other values such as subtotals, totals, taxes, discount percentages, etc are recalculated and the state gets updated. This keeps all of my “business logic” within the reducer. The invoice component simply displays the state of the invoice and is purely presentational.

The problem I run into is that I want to store the computed values that the reducer creates back into my DB. I want this mainly so I can quickly query stats about several invoices at once later on another dashboard, without having to recompute values on demand.

If I make the computations and save them to the DB in the redux thunk, then I would have to deal with having business logic in two separate places if I make this a common practice.

How could I solve this problem without creating side effects in my reducer and maintaining my business logic in a single place?

I’m probably missing something here, but if you call a Meteor.method in your reducer to update the database with the newly recomputed values, how would your business logic be in two separate places?

What if you kept the business logic server-side using hooks or other methods to update the calculated fields? Then you could just pull those fields into your store like normal.

This seems like a bad idea, shouldn’t a reducer be purely functional?

Well, up until now I’ve kept my business logic in my reducers, but it seems like I might have to put any logic that requires server-side features into action creators using redux-thunk.

Like I said, I think I’m missing something. If your thunk is in charge of updating the document in MongoDB corresponding to the invoice, why not update the invoice there too? If the process of updating an invoice means that you have some analytic bookkeeping to do then you should be making reference to it here somehow. Maybe this action is the place to have a Meteor Method side effect of updating your alalytics db.

I really enjoy react/redux but this is my main problem with it… you spend more time abstracting yourself to oblivion that you hardly get anything done.

I’d either do it in your first action, dispatch 2 actions or deal with my reducer having a side-effect.

Well the thunk is currently pretty simple, it just updates a value for a key with minimongo. I suppose what I can do though is just create a meteor method and handle more complex logic there. The thunk can just call that and then dispatch with the results on the callback.

I do agree the abstraction into oblivion can slow things down, but I’d hope over time things will speed up as my thinking gets clearer.

Man, I hear you. A few months back I had a mini meltdown over how long it was taking me to add the simplest of features and just moved stuff back to a global ReactiveDict. I love the redux dev tools and easy testability but it can be a bit demoralising how much code needs writing.

3 Likes

One thing I just haven’t been able to grok very well is where Redux fits in if I want users to edit fields for documents stored in the DB.

Clearly I need to get the state of the document from the server because otherwise I can’t have updates come in reactively if other users happen to be editing the document at the same time for instance. I do this right now using containers that fetch Meteor data.

For example if I add items to an invoice I need those changes to be saved straight to the DB so other users can see the changes right away. So what’s the point of maintaining the document state in Redux? Is time travel and debugging the only benefit?

1 Like