Giter Site home page Giter Site logo

Comments (8)

brianegan avatar brianegan commented on July 19, 2024 1

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:

  1. If you have one TabBar in the app, create a StatefulWidget. For example: TabScreen. Create a static GlobalKey<TabScreenState>. Create a companion TabScreenState class with a public TabController inside. Then, write a Middleware 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);
  }
}
  1. 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.

brianegan avatar brianegan commented on July 19, 2024 1

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.

brianegan avatar brianegan commented on July 19, 2024 1

Also, would love to hear how you solve it in the end! Thanks again for writing :)

from flutter_redux.

brianegan avatar brianegan commented on July 19, 2024 1

@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.

brianegan avatar brianegan commented on July 19, 2024 1

Closing for now. Please let me know if you'd like me to re-open :)

from flutter_redux.

bdiegel avatar bdiegel commented on July 19, 2024

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.

brianegan avatar brianegan commented on July 19, 2024

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.

brianegan avatar brianegan commented on July 19, 2024

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)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.