Comments (8)
Hey there, thanks for writing in :) This is one of the tricky situations! While most of Flutter is Reactive, some parts are imperative: the Navigator
, TextEditingController
and TabController
. Since Redux is Reactive, it can make these situations a bit confusing.
The simplest thing: Would it be possible to call the tabController.animateTo(index)
within an onPressed
callback, before you dispatch the action?
If not, in this case, using the StoreConnector
might not be the best solution. Instead, I could think of a couple options:
- If you have one
TabBar
in the app, create aStatefulWidget
. For example:TabScreen
. Create a staticGlobalKey<TabScreenState>
. Create a companionTabScreenState
class with a publicTabController
inside. Then, write aMiddleware
that listens for the actions that update the state. It would look like this:
void tabNavigationMiddleware(Store<AppState> store, action, NextDispatcher next) {
// Send the action to your Reducer, it will update the app State
next(action);
// Update the TabController if it's an action we care about
if (action is TabNavigationAction) {
TabScreen.key.currentState.controller.animateTo(store.state.tabIndex);
}
}
- If you have multiple screens with Tabs, you could dispatch the
controller
as part of the action, and use that in your Middleware:
class TabNavigationAction {
final TabController controller;
final String someOtherData;
TabNavigationAction(this.controller, this.someOtherData);
}
void tabNavigationMiddleware(Store<AppState> store, action, NextDispatcher next) {
// Send the action to your Reducer, it will update the app State
next(action);
// Update the TabController if it's an action we care about
if (action is TabNavigationAction) {
action.controller.animateTo(store.state.tabIndex);
}
}
Great question! Do any of these options work for ya?
from flutter_redux.
I think you could also do this with a StoreConnector
... for some reason running a function inside the builder
method feels "wrong" because I think the builder should be a pure function, but there's really nothing stopping you from using it this way. It might lead to less gymnastics than doing the Middleware stuff.
This is actually making me wonder whether I should add an onChange
callback to the StoreConnector
... as a place to interact with Imperative APIs
class MyAppBar extends StatelessWidget implements PreferredSizeWidget {
final TabController controller;
MyAppBar({Key key, this.controller}) : super(key: key);
@override
Widget build(BuildContext context) {
return new StoreConnector<AppState, int>(
converter: (store) => store.state.tabIndex,
builder: (context, tabIndex) {
controller.animateTo(tabIndex);
return new AppBar(
bottom: new TabBar(
controller: controller,
tabs: [
new Tab(icon: new Icon(Icons.directions_car)),
new Tab(icon: new Icon(Icons.directions_transit)),
new Tab(icon: new Icon(Icons.directions_bike)),
],
),
title: new Text('Tabs Demo'),
);
}
);
}
@override
Size get preferredSize => new Size.fromHeight(kToolbarHeight);
}
from flutter_redux.
Also, would love to hear how you solve it in the end! Thanks again for writing :)
from flutter_redux.
@bdiegel Hey there! With help from the community, I've published a new version of Redux: 0.3.6 for Dart 1 or 0.4.0 for Dart 2.
This includes a new onWillChange
callback that runs before the builder function. It's meant to give folks an "escape hatch" to work with imperative APIs, such as the TabController
. Might be interesting to give this technique a shot and see how it works out! Would love any feedback if ya do.
from flutter_redux.
Closing for now. Please let me know if you'd like me to re-open :)
from flutter_redux.
Thanks for the detailed explanation.
I'm pondering the second technique. My specific problem is not knowing what tabs to display until after loading user preferences and fetching some data from a REST API.
Initially my AppBar.bottom
is null. Middleware
fetches the necessary content when OnUserPrefsLoadedAction
triggers. Once the data is fetched we update the store and want to rebuild the AppBar
.
The on-boarding case is similar, with the addition that we first need to gather some information from the user and store it in user preferences. And it is also possible for the user to add/remove tabs.
I am just learning Flutter and have no prior experience with Redux, but this is the approach I have been taking. I am not sure if an imperative style callback would make more sense or not.
from flutter_redux.
Yah, that's an interesting problem for sure :) Overall, sounds like what you've got makes total sense. I think it will get tricky with some of those use-cases, such as adding / removing tabs. In those cases, you might have to listen to the Store directly in a StatefulWidget
and rebuild the TabController
when changes occur.
from flutter_redux.
Heya @bdiegel, is it cool if I close this issue? Happy to help more if you'd like me to keep it open, just trying to keep things tidy!
from flutter_redux.
Related Issues (20)
- 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
- Is flutter redux actively maintained HOT 1
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.