A library that connects Widgets to a Redux Store

Last update: May 16, 2022

flutter_redux

Build Status codecov

A set of utilities that allow you to easily consume a Redux Store to build Flutter Widgets.

This package supports null-safety and is built to work with Redux.dart 5.0.0+.

Redux Widgets

  • StoreProvider - The base Widget. It will pass the given Redux Store to all descendants that request it.
  • StoreBuilder - A descendant Widget that gets the Store from a StoreProvider and passes it to a Widget builder function.
  • StoreConnector - A descendant Widget that gets the Store from the nearest StoreProvider ancestor, converts the Store into a ViewModel with the given converter function, and passes the ViewModel to a builder function. Any time the Store emits a change event, the Widget will automatically be rebuilt. No need to manage subscriptions!

Examples

  • Simple example - a port of the standard "Counter Button" example from Flutter
  • Github Search - an example of how to search as a user types, demonstrating both the Middleware and Epic approaches.
  • Todo app - a more complete example, with persistence, routing, and nested state.
  • Timy Messenger - large open source app that uses flutter_redux together with Firebase Firestore.

Companion Libraries

Usage

Let's demo the basic usage with the all-time favorite: A counter example!

Note: This example requires flutter_redux 0.4.0+ and Dart 2! If you're using Dart 1, see the old example.

import 'package:flutter/material.dart';
import 'package:flutter_redux/flutter_redux.dart';
import 'package:redux/redux.dart';

// One simple action: Increment
enum Actions { Increment }

// The reducer, which takes the previous count and increments it in response
// to an Increment action.
int counterReducer(int state, dynamic action) {
  if (action == Actions.Increment) {
    return state + 1;
  }

  return state;
}

void main() {
  // Create your store as a final variable in the main function or inside a
  // State object. This works better with Hot Reload than creating it directly
  // in the `build` function.
  final store = Store<int>(counterReducer, initialState: 0);

  runApp(FlutterReduxApp(
    title: 'Flutter Redux Demo',
    store: store,
  ));
}

class FlutterReduxApp extends StatelessWidget {
  final Store<int> store;
  final String title;

  FlutterReduxApp({Key key, this.store, this.title}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    // The StoreProvider should wrap your MaterialApp or WidgetsApp. This will
    // ensure all routes have access to the store.
    return StoreProvider<int>(
      // Pass the store to the StoreProvider. Any ancestor `StoreConnector`
      // Widgets will find and use this value as the `Store`.
      store: store,
      child: MaterialApp(
        theme: ThemeData.dark(),
        title: title,
        home: Scaffold(
          appBar: AppBar(
            title: Text(title),
          ),
          body: Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                // Connect the Store to a Text Widget that renders the current
                // count.
                //
                // We'll wrap the Text Widget in a `StoreConnector` Widget. The
                // `StoreConnector` will find the `Store` from the nearest
                // `StoreProvider` ancestor, convert it into a String of the
                // latest count, and pass that String  to the `builder` function
                // as the `count`.
                //
                // Every time the button is tapped, an action is dispatched and
                // run through the reducer. After the reducer updates the state,
                // the Widget will be automatically rebuilt with the latest
                // count. No need to manually manage subscriptions or Streams!
                StoreConnector<int, String>(
                  converter: (store) => store.state.toString(),
                  builder: (context, count) {
                    return Text(
                      'The button has been pushed this many times: $count',
                      style: Theme.of(context).textTheme.display1,
                    );
                  },
                )
              ],
            ),
          ),
          // Connect the Store to a FloatingActionButton. In this case, we'll
          // use the Store to build a callback that will dispatch an Increment
          // Action.
          //
          // Then, we'll pass this callback to the button's `onPressed` handler.
          floatingActionButton: StoreConnector<int, VoidCallback>(
            converter: (store) {
              // Return a `VoidCallback`, which is a fancy name for a function
              // with no parameters and no return value. 
              // It only dispatches an Increment action.
              return () => store.dispatch(Actions.Increment);
            },
            builder: (context, callback) {
              return FloatingActionButton(
                // Attach the `callback` to the `onPressed` attribute
                onPressed: callback,
                tooltip: 'Increment',
                child: Icon(Icons.add),
              );
            },
          ),
        ),
      ),
    );
  }
}

Purpose

One question that reasonable people might ask: Why do you need all of this if StatefulWidget exists?

My advice is the same as the original Redux.JS author: If you've got a simple app, use the simplest thing possible. In Flutter, StatefulWidget is perfect for a simple counter app.

However, say you have more complex app, such as an E-commerce app with a Shopping Cart. The Shopping Cart should appear on multiple screens in your app and should be updated by many different types of Widgets on those different screens (An "Add Item to Cart" Widget on all your Product Screens, "Remove Item from Cart" Widget on the Shopping Cart Screen, "Change quantity" Widgets, etc).

Additionally, you definitely want to test this logic, as it's the core business logic to your app!

Now, in this case, you could create a Testable ShoppingCart class as a Singleton or Create a Root StatefulWidget that passes the ShoppingCart Down Down Down through your widget hierarchy to the "add to cart" or "remove from cart" Widgets.

Singletons can be problematic for testing, and Flutter doesn't have a great Dependency Injection library (such as Dagger2) just yet, so I'd prefer to avoid those.

Yet passing the ShoppingCart all over the place can get messy. It also means it's way harder to move that "Add to Item" button to a new location, b/c you'd need up update the Widgets throughout your app that passes the state down.

Furthermore, you'd need a way to Observe when the ShoppingCart Changes so you could rebuild your Widgets when it does (from an "Add" button to an "Added" button, as an example).

One way to handle it would be to simply setState every time the ShoppingCart changes in your Root Widget, but then your whole app below the RootWidget would be required to rebuild as well! Flutter is fast, but we should be smart about what we ask Flutter to rebuild!

Therefore, redux & redux_flutter was born for more complex stories like this one. It gives you a set of tools that allow your Widgets to dispatch actions in a naive way, then write the business logic in another place that will take those actions and update the ShoppingCart in a safe, testable way.

Even more, once the ShoppingCart has been updated in the Store, the Store will emit an onChange event. This lets you listen to Store updates and rebuild your UI in the right places when it changes! Now, you can separate your business logic from your UI logic in a testable, observable way, without having to Wire up a bunch of stuff yourself!

Similar patterns in Android are the MVP Pattern, or using Rx Observables to manage a View's state.

flutter_redux simply handles passing your Store down to all of your descendant StoreConnector Widgets. If your State emits a change event, only the StoreConnector Widgets and their descendants will be automatically rebuilt with the latest state of the Store!

This allows you to focus on what your app should look like and how it should work without thinking about all the glue code to hook everything together!

Contributors

GitHub

https://github.com/brianegan/flutter_redux
Comments
  • 1. Error after updating to 0.4.0

    Hey @brianegan

    after updating to 0.4.0 Im getting the following error. Any idea what could cause the issue?

    ══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞══
    The following NoSuchMethodError was thrown building StoreConnector<AppState,
    Store<AppState>>(dirty):
    The getter 'store' was called on null.
    Receiver: null
    Tried calling: store
    

    flutter Doctor

    [✓] Flutter (Channel master, v0.2.4-pre.64, on Mac OS X 10.13.3 17D102, locale en-DE)
        • Flutter version 0.2.4-pre.64 at /Users/eikebartels/Applications/flutter
        • Framework revision 619ebd67a9 (5 hours ago), 2018-03-20 00:26:10 -0700
        • Engine revision c3ab0c9143
        • Dart version 2.0.0-dev.39.0.flutter-f1ebe2bd5c
    

    Main

    void main() {
      final store = new Store<AppState>(
        appStateReducer,
        initialState: new AppState.loading(),
        middleware: createStoreMiddleware()
      );
      runApp(new App(store: store));
    }
    

    App

    class App extends StatelessWidget {
      final Store store;
    
      App({Key key, this.store }) : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        return new StoreProvider<AppState>(
          store: store,
          child: new MaterialApp(
            theme: AppTheme.theme,
            routes: {
              "/": (context) {
                return new StoreBuilder<AppState>(
                    builder: (context, store) {
                      return new OnBoarding();
                    });
              }
            },
          ),
        );
      }
    }
    
    Reviewed by lasseschmitt at 2018-03-20 12:40
  • 2. Provide a way to use StoreBuilder/StoreConnector without using StoreProvider to get the Store

    StoreConnector and StoreBuilder (which just wraps a StoreConnector) force you to use StoreProvider to get the store they are going to listen to. But there are times when you already have a reference to the store at the time you are constructing the StoreBuilder or StoreConstructor and having them use StoreProvider to get the store is just extra work.

    For example, you might have a StoreBuilder with rebuild on change set to false because you have some buttons that need to call store.dispatch, but next to them you have a widget that needs to rebuild based on changes to part of the state. You want to only rebuild that widget when that particular part of the state changes and that is the only widget that needs to rebuild. So you wrap that widget in a store connector with distinct on. But having that StoreConnector use the StoreProvider to find the Store is unnecessary work.

    I am also looking at this because I am looking at structuring my redux so that there is a global Store with the state for the entire app and also the ability to have child Stores that are specific to a view/page and that Store only exists while that view is in existence and goes away when that view/page goes away. In this case the Store is passed to the constructor of the view/page. Having to create a StoreProvider to provide the Store is extra hassle since the Store is stored in the state of the view/page. One of the justifications for this hierarchical state is that you might have multiple of these views on screen at the same time and they each need their own state.

    So one way to handle this is to have an optional store parameter on StoreBuilder/StoreConnector that if set is the store that is listened to. If it is not set use StoreProvider.

    Or alternatively it could be a storeProvider parameter which is function from BuildContext to Store and it has a default value which is to call StoreProvider.

    Alternatively, I would be equally satisfied if _StoreStreamListener were simply made public, since StoreConnector is nothing more than a shallow wrapper around _StoreStreamListener that only adds the call to get the Store from StoreProvider and some asserts on parameters.

    Reviewed by dalewking at 2019-02-27 15:19
  • 3. Scrolling down to bottom of screen when Redux store changes

    Hi Brian,

    I'm trying to build a small chat app with Redux, and when new list items (chat messages) are added to the store I want to animate a scroll down to the bottom of the list so they are in view.

    Without Redux, in Flutter you're able to use ScrollController then call _scrollController.animateTo when you call setState to add the new items (source).

    In React, you would have componentDidUpdate, so you would be able to animate the scroll to the bottom in componentDidUpdate when your Redux store changes (source).

    Wondering what is the equivalent way to do this in Redux with Flutter since StatelessWidget doesn't provide hooks like componentDidUpdate? Unfortunately, just calling _scrollController.animateTo after dispatching a Redux action doesn't scroll to the bottom position after the Redux store updates.

    Reviewed by hash404 at 2018-05-12 07:24
  • 4. Accessing store in StoreConnector.builder

    Hi,

    I need to have access to the store in the builder function so I can dispatch calls to the middleware. Is there a way to do this "nicely" without storing the store during the call to onInit?

    I am new to dart and I just cannot see how to do this.

    The use case I am looking at is having a widget display some stateful data and a button. The button when pressed should invoke the store.dispatch(new SomeAction());

    Paul

    Reviewed by Paul-Todd at 2018-04-07 20:23
  • 5. Error: No StoreProvider found. To fix, please try: * Using Dart 2 (required) by using the --preview-dart-2 flag * Wrapping your MaterialApp with the StoreProvider, rather than an individual Route *

    Time to time getting Crashlytcis report like this:

    Non-fatal Exception: package:flutter_redux/flutter_redux.dart 29 in StoreProvider.of Error: No StoreProvider<AppState> found. To fix, please try: * Using Dart 2 (required) by using the --preview-dart-2 flag * Wrapping your MaterialApp with the StoreProvider<State>, rather than an individual Route * Providing full type information to your Store<State>, StoreProvider<State> and StoreConnector<State, ViewModel> If none of these solutions work, please file a bug at: https://github.com/brianegan/flutter_redux/issues/new

    Note: In the app regulary using the Redux and it works fine.

    Here is the app snippet:

    import 'dart:async';
    import 'package:driveddy/app/app_state.dart';
    import 'package:driveddy/app/app_state_reducer.dart';
    import 'package:driveddy/app/middleware.dart';
    import 'package:driveddy/app/routes.dart';
    import 'package:driveddy/app/theme.dart';
    import 'package:driveddy/localization/fallback_cupertino_localization_delegate.dart';
    import 'package:driveddy/values/keys.dart';
    import 'package:flutter/cupertino.dart';
    import 'package:flutter/material.dart';
    import 'package:flutter_app_badger/flutter_app_badger.dart';
    import 'package:flutter_localizations/flutter_localizations.dart';
    import 'package:flutter_redux/flutter_redux.dart';
    import 'package:redux/redux.dart';
    
    class App extends StatefulWidget {
      @override
      _AppState createState() => _AppState();
    }
    
    class _AppState extends State<App>  {
      
      static Store<AppState> store = new Store<AppState>(
        appStateReducer,
        initialState: new AppState.loading(),
        middleware: createMiddleware(),
      );
    
      @override
      Widget build(BuildContext context) {
        return new StoreProvider<AppState>(
          store: store,
          child: new StoreConnector<AppState, _ViewModel>(
            converter: _ViewModel.fromStore,
            distinct: true,
            builder: (context, vm) {
              return new MaterialApp(
                localeResolutionCallback: (deviceLocale, supportedLocales) {
                  return deviceLocale;
                },
                localizationsDelegates: [
                  GlobalMaterialLocalizations.delegate,
                  GlobalWidgetsLocalizations.delegate,
                  const FallbackCupertinoLocalizationsDelegate(),
                ],
                showPerformanceOverlay: vm.isDebug,
                navigatorKey: Keys.navigator,
                theme: AppTheme.theme,
                initialRoute: Routes.initialRoute,
                routes: Routes.routes(context),
              );
            },
          ),
        );
      }
    }
    

    This is the screen where the issue is happening:

    @override
     Widget build(BuildContext context) {
       _setIsDisposable(context: context, isDisposable: false);
         return  new Text(
                       "some text",
                       textAlign: TextAlign.center,
                       maxLines: 4,
                       style: new TextStyle(fontSize: 16.0, height: 1.25, color: AppTheme.gray7),
                     );
     }
    
     void _setIsDisposable({@required BuildContext context, @required bool isDisposable}) {
       StoreProvider.of<AppState>(context).dispatch(new SetIsSignUpStackDisposableAction(isDisposable: isDisposable));
     }
    
    

    Doctor summary (to see all details, run flutter doctor -v):

    [✓] Flutter (Channel beta, v1.0.0, on Mac OS X 10.13.6 17G65, locale en-DE)
    [✓] Android toolchain - develop for Android devices (Android SDK 28.0.3)
    [✓] iOS toolchain - develop for iOS devices (Xcode 10.1)
    [✓] Android Studio (version 3.3)
    [!] VS Code (version 1.30.2)
    [✓] Connected device (1 available)
    
    Reviewed by Abgaryan at 2019-01-23 11:09
  • 6. onInitialBuild called multiple time on child container when parent container changes

    Hi all, I have a question regarding container that have other container. Basically I have a container that can display loading status and error message. It is a sort of "shell" container. On this container I have a child container with its own viewmodel and nothing shared. I can see the onInitialBuild method on the child container is called every time the mainshell onInitialBuild is changed. Is this an expected behavior?

    Reviewed by AlexandreRoba at 2018-06-20 18:35
  • 7. How do I dispatch actions to the Store without building a widget?

    Hi there.

    How was your trip? 😄

    I've been happily using flutter_redux, but I'm having trouble with one thing in particular. I want some methods inside my Widgets to dispatch actions to the Store from the StoreProvider, but not necessarily build a widget.

    Since StoreConnector() is only intended for passing the store to a Widget in the context of the build method, I'm wondering: is there any class or function I can use inside of a method that returns void (for example) that just provides me with the Store, so I can dispatch an action to it without needing to build a widget?

    Thank you.

    Reviewed by jeroen-meijer at 2018-05-19 01:39
  • 8. Fix StoreProvider.of for Reified types

    I'm repeatedly getting

    I/flutter ( 9311): ══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════
    I/flutter ( 9311): The following NoSuchMethodError was thrown building StoreConnector<int, Store<int>>(dirty):
    I/flutter ( 9311): The getter 'store' was called on null.
    I/flutter ( 9311): Receiver: null
    I/flutter ( 9311): Tried calling: store
    

    error when trying to use StoreBuilder or StoreConnector in the hierarchy. My app widget builds the rest like this:

    @override
    Widget build(BuildContext context) {
      return new StoreProvider<int>(
        store: new Store<int>(
                (i, action) => i + 1,
            initialState: 0
        ),
        child: new MaterialApp(
          title: 'App',
          theme: new ThemeData(
            primarySwatch: Colors.blue,
          ),
          home: new Scaffold(
              appBar: new AppBar(
                title: new Text("App"),
              ),
              body: new MainScreen(),
        ),
      );
    }
    

    I can't get it to work, I understand StoreProvider is a simple InheritedWidget, but even if I try to manually call new StoreProvider.of(context) in a widget down the tree, I get null. I don't understand, since I've created dead simple inherited widget and placed it instead of StoreProvider and I could fetch it with of() method without issues (I almost did a copy-paste from the StoreProvider class).

    The int state and inline reducer is just a result of me trying to simplify the things as much as I can, with no luck. Any idea why would it be like this?

    Reviewed by lwasylkowski at 2018-03-05 17:24
  • 9. Using flutter redux and Refresh Indicator

    Hi,

    Great library, I've really enjoyed implementing it but I've had a bit of a mammoth session and can't seem to wrap my head around this one. I am pretty new to Flutter and Dart so apologies if this is a simple question.

    I want to use a pull to refresh which sends an action and retrieves a new set of items from the web via the middleware. Doing this without the refresh indicator works well, but the indicator needs a Future passed to it that resolves when the action has finished. Is there any way that I can use the existing stock widget to start and stop based on actions?

    Thanks

    Reviewed by oli107 at 2018-01-29 17:51
  • 10. Options for persistence relating to where we put our business logic and using middleware.

    Hi Brian, many thanks for the library once again 👍

    What options do we have / what recomendations can you give for persistance? The main problem I'm having is that I put a lot of my business logic in my reducers. This seemed to be working out until I tried to add some persistence middleware

    1. dispatch(new CalculatePersonsAgeAction);
    2. middleware - persist data
    3. reducer - run calculate age logic and update record in the store

    (as you can probably work out the persist will be calculated too early and will save old information, also some of my actions just pass an id such as the following action so I need to lookup the record...

    ToggleExcludedAction(int myId)

    this is handled in my reducer where I look up the object and do a copyWith to alter my record.

    So this was my first problem, I am running my logic before I need to persist it, so...my next plan was to put more of my logic in my actions and I started to use redux thunk where it was necessary to get at the state (ie lookup an existing record by id). My next problem is that now my actions are tied to AppState and my tests aren't as clean becase I need to create AppState (previously I could create a simple Store based on just the data relevant to the reducer).

    ...here is the new Action...

    Function(Store<AppState>) toggleExcludedAction(int myId) {
      return (Store<AppState> store) {
    

    which I feel makes it a little less clear in the test because now I have to create the AppState in my tests where a lot of the data is irrelevant to the test (previously I was just creating just the data that the reducer was based on which made it clear what the data dependencies were). It's not the end of the world but it's just not as clean and wondered if I had missed something or if there is an alternative option.

    I'm now considering just putting the code into a function that accepts the required dependencies and letting the action (which has a dependency on AppState) call that function and only testing my function.

    so I test this

    void userFlagSeen(Function(dynamic) dispatch, List<UserFlag> userFlags, int id) {
      var existingUserFlag = userFlags.firstWhere((uf) => uf.id == id);
      var newUserFlag = existingUserFlag.copyWith(hasSeen: true);
      dispatch(new UserFlagUpdateA(newUserFlag));
    }
    

    but not this

    Function(Store<AppState>) userFlagSeenAction(int lectureId) {
      return (Store<AppState> store) =>
          _userFlagSeenAction(store.dispatch, store.state.userFlags, lectureId);
    }
    

    ok...now I'm overthinking this problem but here is a more type safe class based approach

    class Action<T>{
      Function(Store<AppState>) byId(Actions<T> actions, int id) {
        return (Store<AppState> store) =>
            actions.updateAction(store.dispatch, new T().storeStateFn, id);
      }
    }
    
    abstract class Actions<T> {
      void updateAction(Function dispatch, List<T> objects, int id);
    }
    
    class HasSeen implements Actions<UserFlag> {
      @override
      void updateAction(Function dispatch, List<UserFlag> userFlags, int id) {
        var newUserLecture = new UserFlag(id, true);
        dispatch(new UserFlagUpdateAction(newUserLecture));
      }
    }
    

    calling it like so

    dispatch(new Action<UserFlag>().byId(new HasSeen(), 1))

    there may be an easier way to this though!

    Reviewed by atreeon at 2018-07-17 16:06
  • 11. The getter 'store' was called on null

    Hi,

    I'm trying to implement redux on my flutter app, versions:

      redux: "^3.0.0"
      flutter_redux: "^0.5.0"
    

    When I run my app the error in the title is thrown. I followed the Dart 2 migration guide for both the packages.

    Flutter: 0.2.8 Dart: 2.0.0

    Reviewed by darioielardi at 2018-04-16 16:48
  • 12. Import Store data type

    Hi there,

    First of all, thank you for the wonderful tool. I like it even more than the original JS Redux ,with the support for enums for actions and with Dart's strong typing which allows code suggestions while typing.

    The one request I have is about exposing the Store class used with Redux so it can be imported. I will try to show the code that I currently have after mentioning these benefits I see from doing this.

    1. Can pass store as a function parameter with strong typing. (If I try passing a store as a function parameter now, it has to be of type dynamic which can break depending on other developers.
    2. Better code suggestions from IDE compared to using type dynamic.

    I hope that makes sense. Thanks for your time, and once again, for my favourite way of managing state with Flutter.

    PS: Side question I hope you don't mind.

    If I have multiple forms that I would like to use Redux for, is it better to have:

    1. An ephemeral store for each form separate from the global app state (possibly a better memory optimisation, at the cost of architectural complexity), or
    2. A single global app state with each form data class being nullable and set to null once the form data has been submitted.

    EDIT: I have a function like this, which is called in a loop.

    double calculateDistanceFromUser(dynamic store, LatLng inputPoints) {
      const Distance geo = Distance();
      return geo.as(
        LengthUnit.Kilometer,
        inputPoints,
        LatLng(
          store.state.userLocation.latitude,
          store.state.userLocation.longitude,
        ),
      );
    }
    

    My two choices are to look up the store from the build context each loop iteration (unnecessary computation) or to use type dynamic to represent the store, neither of which is desirable.

    Reviewed by hummy123 at 2022-04-09 18:16
  • 13. [Question]: Mixing global and local state

    Using the StoreConnector it looks to me like all of the view models properties must be derived from the current store data. But what if I want to have some data that should be kept local to the view. Let's say I want to e.g. show an alert once based on an exception that is part of the redux state. For this, I would have a property like showedExceptionAlert in the view model. But whenever the view model gets regenerated the value of this property would get overridden. And I don't want to go the full redux way via actions, reducer... just because of a simple, local-only property.

    For sure I could keep this data in the view, but that feels a little bit wrong to have two places to look for the current state.

    Another option would be to mix e.g. the bloc pattern with redux but this also seems a little bit too much for such a simple task.

    So the question is: Is there something like a pattern to have local and global (redux) state in one view model?

    Reviewed by hffmnn at 2021-10-12 19:04
  • 14. Receive the action that caused the state update in StoreConnector hooks

    Hi, I was wondering if there's a way to receive the last action that produced the state in StoreConnector.ignoreChange?

    Use case: This is for performance tuning. So we can ignore a part of the state update when we are sure that only a certain action can cause that part of the state to be changed. In this case, producing a new ViewModel could be skipped, because it is expensive.

    Reviewed by ylilarry at 2021-10-08 21:36
  • 15. The value 'null' can't be assigned to a variable of type 'ViewModel' because 'ViewModel' is not nullable.

    .. flutter/.pub-cache/hosted/pub.dartlang.org/flutter_redux-0.8.2/lib/flutter_redux.dart:507:22: Error: The value 'null' can't be assigned to a variable of type 'ViewModel' because 'ViewModel' is not nullable.

    Error: The value 'null' can't be assigned to a variable of type 'ViewModel' because 'ViewModel' is not nullable. _latestValue = null; ^ FAILURE: Build failed with an exception.

    • Where: Script 'D:\flutter SDK\flutter\packages\flutter_tools\gradle\flutter.gradle' line: 1005
    Reviewed by HussainAlMeshaima at 2021-10-06 06:35
  • 16. [Question] different appbar actions based on state / StoreConnector ?

    I have a situation where I want to display different app bar actions based on StoreConnector. However, I don't want to build the entire Scaffold when the state changes, only the AppBar.

    Options I tried / thought of:

    1. Since StoreConnector isn't a PreferredSizeWidget, which is what the appBar argument to Scaffold expect, I can't wrap the entire appbar.
    2. The actions argument expect a list, so I can't wrap that either.
    3. I thought on making a StoreConnector for each possible action, even though that may be null, but we can't return null; so that's not an option.

    Example of what I would of wanted

        return Scaffold(
          appBar: StoreConnector<AppState, AuthState>(
            converter: (appState) => appState.state.auth,
            builder: (context, auth) {
              List<Widget> widgets = [];
              if (auth.isLoggedIn) {
                widgets.add(Icon(Icons.star));
              }
              widgets.add(PopupMenuButton<Object>(...));
              return AppBar(title: 'MyApp', actions: actions);
            },
          body: ...
          ),
        );
    

    What should I do about it?

    Reviewed by matanshukry at 2021-06-04 10:38
  • 17. ViewModel: Function fields vs function literals?

    In many examples (including the TODO architecture sample), ViewModels are created like so:

    class ViewModel {
      final void Function() myFunction;
      final String myProperty;
    
      ViewModel({
        required this.myFunction,
        required this.myProperty,
      });
    
      factory ViewModel.fromStore(Store<AppState> store) {
        return ViewModel(
          myFunction: () => store.dispatch(const MyFunctionAction()),
          myProperty: store.state.myProperty,
        );
      }
    }
    

    This (IMO) has the following problems

    • myFunction may be accidentally used in a == or hashCode implementation, which would be incorrect as the closure would be non-identical with every new ViewModel
    • More RAM usage (maybe?)

    Why is that the recommended approach, compared to something like this?

    class ViewModel {
      final Store<AppState> _store;
    
      ViewModel(this._store) : myProperty = _store.state.myProperty;
    
      final String myProperty;
    
      void myFunction() => _store.dispatch(const MyFunctionAction());
    }
    
    Reviewed by hacker1024 at 2021-04-05 09:11

Related

Dart web3 - A dart library that connects and interacts with the Ethereum blockchain

dart_web3 A dart library that connects and interact with the Ethereum blockchain

Feb 17, 2022
Ethers: A dart library that connects to interact with the Ethereum blockchain and inspired by ethers.js

Ethers For Flutter Ethers is a dart library that connects to interact with the Ethereum blockchain and inspired by ethers.js. Thanks to web3dart which

Mar 24, 2022
dart based login-screen that connects with Firebase Auth to enable users to sign-in
dart based login-screen that connects with Firebase Auth to enable users to sign-in

A Flutter / Firebase login screen A simple flutter/dart based login-screen that connects with Firebase Auth to enable users to sign-in/up with Email o

Nov 20, 2021
A lightweight flutter plugin to check if your app is up-to-date on Google Play Store or Apple App Store

App Version Checker this package is used to check if your app has a new version on playstore or apple app store. or you can even check what is the lat

Dec 23, 2021
Phone-Store-App-UI-Flutter - Flutter Phone E-Store App UI with support for dark and light mode
Phone-Store-App-UI-Flutter - Flutter Phone E-Store App UI with support for dark and light mode

Phone-Store-App-UI-Flutter - Flutter Phone E-Store App UI with support for dark and light mode

Apr 30, 2022
Shoes-Store-App-UI-Flutter - Beautiful Shoes Store App UI with support for dark and light mode
Shoes-Store-App-UI-Flutter - Beautiful Shoes Store App UI with support for dark and light mode

Flutter Shoes Store App UI with support for dark and light mode. Flutter 2.8.1 N

Apr 30, 2022
Flitter Hadrien Lejard Kevin SegaudFlitter [182⭐] - Glitter app by Hadrien Lejard and Kevin Segaud. It uses Redux and Jaguar.
Flitter Hadrien Lejard Kevin SegaudFlitter [182⭐] - Glitter app by Hadrien Lejard and Kevin Segaud. It uses Redux and Jaguar.

flitter Gitter Client for Mobile made with Flutter Getting Started For help getting started with Flutter, view our online documentation. Configuration

May 5, 2022
Flutter app backed by Redux, shows animations, internationalization (i18n), ClipPath, fonts and others...
Flutter app backed by Redux, shows animations, internationalization (i18n), ClipPath, fonts and others...

A Flutter tourism app that is backed-by Redux, shows animations, internationalization (i18n, English <=> Arabic), ClipPath, and fonts. YouTube demo I

May 9, 2022
A simple flutter app with demo implementation of redux.
A simple flutter app with demo implementation of redux.

Flutter Redux Tutorial Redux Project is just a quick guide for implementation of redux.dart and flutter_redux . Written in dart using Flutter SDK. Ple

Sep 29, 2021
Starter project and code generator for Flutter/Redux
Starter project and code generator for Flutter/Redux

Flutter Redux Starter/Code Generator Videos Short video ~ 1 minute Long video ~ 10 minutes We're using this approach to develop the Flutter app for In

May 1, 2022
Podcast app with Flutter & Redux
Podcast app with Flutter & Redux

Podcast App - Flutter & Redux Preview Introduction I have built a basic podcast app with an interactive UI, as well as some of its functionalities : L

Apr 9, 2022
A Redux version tailored for Flutter, which is easy to learn, to use, to test, and has no boilerplate
A Redux version tailored for Flutter, which is easy to learn, to use, to test, and has no boilerplate

A Redux version tailored for Flutter, which is easy to learn, to use, to test, and has no boilerplate. Allows for both sync and async reducers.

May 3, 2022
FlutterDux - Redux.JS driven Flutter

FlutterDux Flutter + Redux.js Android only at the moment, iOS coming soon. Getting Started Check out this article for a description of how it works. L

Jul 28, 2019
Redux for Dart

Redux for Dart using generics for typed State. It includes a rich ecosystem of Docs, Middleware, Dev Tools and can be combined with Flutter using the

May 13, 2022
Flutter-Movie - 😎 🎬 A Flutter movie app build with Fish-Redux and The Movie DB api.
Flutter-Movie - 😎 🎬 A Flutter movie app build with Fish-Redux and The Movie DB api.

movie A Flutter movie app build with Fish-Redux and TMDB api. ToDos redesign UI account detail customize stream support dark mode support localization

May 22, 2022
Github Trending app built with Flutter+Redux+Built(Immutable Data)

Github Trending app built with Flutter+Redux+Built(Immutable Data)

May 13, 2020
Structured and Organized Flutter (ANDROID+WEB) template project using Redux architecture and Retrofit rest package

flutter_redux_template A new Flutter project. JSON Models classes need this lines to json generator: part 'foo.g.dart'; //on imports factory Foo.from

Apr 11, 2022
This Dart package offers developers a streamlined library of Flutter widgets, useful for expanding widgets and text views, when users interact with them.
This Dart package offers developers a streamlined library of Flutter widgets, useful for expanding widgets and text views, when users interact with them.

This Dart package offers developers a streamlined library of Flutter widgets, useful for expanding widgets and text views, when users interact with them.

Feb 26, 2022
:fire:GeoFlutterFire:fire: is an open-source library that allows you to store and query firestore documents based on their geographic location.
:fire:GeoFlutterFire:fire: is an open-source library that allows you to store and query firestore documents based on their geographic location.

GeoFlutterFire ?? GeoFlutterFire is an open-source library that allows you to store and query a set of keys based on their geographic location. At its

May 25, 2022
In this repo you will see how to pick images from the image library and also, see how to store the selected images on Firebase.
In this repo you will see how to pick images from the image library and also, see how to store the selected images on Firebase.

flutterimageapp Flutter Tutorial - Upload Images using Firebase Storage. Flutter Tutorial - Upload Images using Firebase Storage Video series can be w

May 3, 2022