-
Notifications
You must be signed in to change notification settings - Fork 219
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Middleware that acts as NavigatorObserver #39
Comments
Kent! Stop finding all the tough edge cases!!! :P Jokes, of course, really interesting problem, thanks for writing in :) I'll be honest, even though you've provided a really good description, I feel like I don't have enough of a handle on your problem to give you solid advice because it's a tricky one with Edge cases I probably don't understand. But let me try...
Since the above does look complex, and I could also see edge cases creeping in, could you test your views to ensure they're firing the right actions at the right times? Or could you perhaps elaborate on why it was terrible? I'd be interested in hearing the problems it created. Since it seems starting / stopping these actions is related to showing / hiding Widgets, that still feels like the cleanest way given my limited knowledge. |
Haha! I'm very grateful that I have you to bounce ideas and questions off, Brian. Feeling a bit lonely as the only flutter/redux/Dart dev at my company... Perhaps this diagram I whipped up provides a better visualization for my scenario: So you can see that items consist of sub-items. Users can add or edit items, and add or edit sub-items within those items. At any point in the process, they could bail out by hitting the back button, and what that does is contingent upon where they are in the process. Moreover, because the data has multiple levels to it (items and sub-items), I can simply take a single snapshot. Otherwise, a user might start editing an item, start editing a sub-item within that item, then bail out on editing that sub-item. Doing so should roll back only the sub-item changes, not the entire item. Anyway, the point is that whilst I have all this working, it's a bit icky to me. Also, not evident from the above diagram (it was getting too busy!) is the fact that items (and sub-items) can also be deleted via a swipe gesture. When this happens, a transaction is started, the (sub)item is deleted, and a snackbar is shown with an UNDO action. If the user hits UNDO, the transaction is rolled back. If the snackbar is dismissed for any other reason, the transaction is committed. Alas, I had to drive this part of the process from the UI rather than middleware, since I simply couldn't find a sane way to do otherwise. Not sure if I've made things clearer here or worse 🙃 No real expectations for an answer or anything. I guess I just wondered whether I might be overlooking some simpler way of achieving this and having the code for it all in one spot as middleware. |
Heya @kentcb -- even with the detailed breakdown, still not quite sure I could come up with a good solution without sitting down with ya for a bit and hacking away at it! I can't think of anything obvious, as it does seem like there's some tricky logic in there and it would be tough to give an obvious solution without working through all the corner cases :) |
Yep, totally understand @brianegan. Thanks for having a look anyway. I'm more or less happy with how my code is functioning - I'm just not certain it's the best design. I've chalked it up as potential tech debt and moved on. |
Hello! Here's another tasty design question with respect to redux and flutter...
I need to support undo in my app, so that users can wantonly and confidently enact destructive changes, and also so that state management is generally easier. In my case, I have a hierarchy of items, and items within those items. Users can add/edit/delete (and undo those deletions). So something as simple as hitting an ADD button, then hitting the navigation's back button needs to intelligently manage state.
My implementation is based on a stack of immutable (built) DTOs that are within my state. Then there are three actions to manage this state (
BeginTransaction
,CommitTransaction
,RollbackTransaction
). This part was really easy to get up and running. The reducers just do what you'd expect, and include assertions to ensure that the state maintains its integrity (always at least one item on the stack).The hard part was figuring out where to dispatch these actions and finding a way to somewhat guarantee that transactions will remain balanced. Initially, I just sprinkled them through my views. It worked, but was terrible and I'm pretty sure there were some edge cases that I'd missed. I abandoned that and attempted to manifest transactions solely within middleware. Sounds an attractive proposition, but it was difficult/impossible to achieve cleanly.
Here's a look at my middleware that handles this:
And here are the main problems I have with this approach:
CompositeNavigatorObserver
class, which just manages any number ofNavigatorObserver
instances, forwarding all events onto them. I pass thisCompositeNavigatorObserver
into myMaterialApp
. This allows the middleware to monitor and react to navigation events. I could not think of a cleaner way.Store
instance, and other times it's passed in so I don't have to. I also usedScaffold.of
at one point, but that was no better (and was messier).true
when editing completes successfully. This was also a bit messy (in a separate piece of middleware).OK, sorry for the rando post again. Really just interested in hearing any thoughts on this direction or how it could be improved.
Thanks!
The text was updated successfully, but these errors were encountered: