Comments (7)
OK, I completely missed the intrinsic view model support. I thought I'd be adding extra complexity by introducing VMs, but turns out they're exactly how I should be handling formatting/validation, so that's 👍
One final point of confusion for me was integrating redux into flutter's validation mechanism (Form
and TextFormField
, for example). I think the two are fundamentally incompatible, but I also think it probably doesn't matter. I can just forgo the validation mechanism and assign any error text myself during the widget build (based on my VM).
Trying this out today...
from flutter_redux.
Hey hey! Thanks for writing in :) At least for formatting text, the ViewModel approach is definitely the way I'd encourage folks to go. That way the State object can store the raw DateTime
, and the Views that use that DateTime
can format it however they need for the situation, whether it's "5 mins ago," "Yesterday," or "21 Jan 2081", without having to store different representations in the State object.
Validation is definitely trickier, imo, since the way Form
works requires you to use the build-in validate()
method. As you said, they're a bit incompatible. Therefore, while I can definitely see a case for this logic also being in a middleware since it's "business logic," the best approach I've found is similar to yours: Write a testable function and use it in the View layer with a Form
element's validate
method. It might not be the best, but there's an example of that here: https://github.com/brianegan/flutter_architecture_samples/blob/master/example/redux/lib/presentation/add_edit_screen.dart#L48
The other approach I could think of: Write your own Form Widgets (might necessary anyhow for non-material Forms anyhow). Then put some of this logic in the Middleware, and have it dispatch FormValid
/ FormInvalid
type of actions to a Reducer if a given form isn't valid.
Thanks for asking! Interesting topic for sure :)
from flutter_redux.
@brianegan Thanks very much for the reply. I've been at work putting these ideas into an implementation and things are mostly working out very nicely.
One thing that bugs me, and perhaps I'm overlooking something ... when using StoreConnector
, my build logic will of course want access to the VM and BuildContext
, as provided by the ViewModelBuilder<VM>
function. However, it also often needs the store so that it can dispatch actions as appropriate.
But getting ahold of a store from my build logic seems a bit of a hassle. I either need to pass the store into my VM, which feels unnatural and makes unit testing harder. Or I need to do something like this:
@override
Widget build(BuildContext context) =>
new StoreConnector<AppState, LoginPageViewModel>(
converter: (Store<AppState> store) =>
new LoginPageViewModel(store.state.loginState),
builder: (BuildContext context, LoginPageViewModel viewModel) => _buildPage(context, new StoreProvider.of(context).store, viewModel),
);
Widget _buildPage(BuildContext context, Store<AppState> store, LoginPageViewModel viewModel) {
Which I also find clunky.
Should ViewModelBuilder<VM>
also provide access to the store, or am I missing something pretty obvious here?
from flutter_redux.
Heya @kentcb :) Glad it's generally working out!
The short answer: the ViewModel
can be / contain functions that call store.dispatch
.
Or within a Class: https://github.com/brianegan/flutter_architecture_samples/blob/master/example/redux/lib/containers/extra_actions_container.dart#L29
For testing, that makes it really easy! You can simply create a stub implementation of the function for tests and pass it to the View. You can then use the Widget testing utils to find the Button (or whatevs) you've attached the function to, tap it, and then check that your stub was called :)
Does that suit your use case?
from flutter_redux.
Interesting...but, to me, exposing functions from the VM for no purpose other than to provide them to widgets feels just as superfluous as exposing the store itself. Granted, exposing functions certainly decouples the VM from the store, but it still feels like the VM has more knowledge than it requires. I need to mull over this some more. Thanks Brian.
from flutter_redux.
Sure thing, interesting discussion :)
I gravitate toward putting Store -> Handler transformations in the ViewModel rather than the Widget layer since it's easier to test (it's raw Dart, so you can test a pure Store -> VM function) and because I feel like Functions are data the same way Strings are. It's all just data for the view layer!
But in the end, this is just my take on how to do things. Would love to see better approaches!
from flutter_redux.
Gonna close this out for now, let me know if you have more Qs / want to reopen :)
from flutter_redux.
Related Issues (20)
- [Question]: Mixing global and local state
- How to not accept change notifications when the Router is not at the top level, and then take the initiative to obtain the changes when the Router returns to the top level HOT 1
- onDidChange called twice HOT 8
- Is this package still actively maintained?
- `onWillChange` and `onDidChange` errors are swallowed HOT 4
- Warning related to `?` operator on Linux/Dev channel. HOT 2
- Import Store data type
- Widgets binding error after upgrading flutter version to 2.13.0-0.1.pre HOT 1
- onDidChange not working as expected HOT 3
- Build warning with Flutter 3.0 HOT 5
- flutter_redux depends on flutter_redux, version solving failed HOT 3
- onWillChange and onDidChange called twice after state update HOT 2
- Passing Store as an argument to MethodChannel and Background Isolate
- Question on how to use the reducer right way HOT 2
- [Question]: Any thoughts on difference between ignoreChange and distinct?
- Socket and Flutter_redux HOT 18
- Dispatching an action that does not alter state rerenders the widget, causing an infinite loop HOT 5
- How to watch redux store change inside useEffect? HOT 5
- [Question] is it expected that the store doesn't run until frames render? HOT 1
- After push a new page, and Dispatching an action, there is an infinite loop
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from flutter_redux.