Skip to content
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

Nested State does not update the UI #30

Closed
BerndWessels opened this issue Jun 14, 2018 · 2 comments
Closed

Nested State does not update the UI #30

BerndWessels opened this issue Jun 14, 2018 · 2 comments

Comments

@BerndWessels
Copy link

Hi

I have an AppState and a nested MenuState.
Actions on the AppState trigger the reducer and that then triggers the UI to update.
Actions on the nested MenuState trigger the nested reducer BUT do not trigger the UI to update.

Is this a bug or am I doing something wrong?

If there is nothing obvious in my following code, would you be so kind and provide an example with a nested action and reducer that actually triggers an update using the flutter_built_redux StoreConnection?

Doctor summary (to see all details, run flutter doctor -v):
[√] Flutter (Channel dev, v0.5.4, on Microsoft Windows [Version 10.0.17134.112], locale en-NZ)
[√] Android toolchain - develop for Android devices (Android SDK 26.0.2)
[√] Android Studio (version 3.1)
[√] IntelliJ IDEA Community Edition (version 2017.3)

store

Store<AppState, AppStateBuilder, AppActions> createStore() {
  return new Store<AppState, AppStateBuilder, AppActions>(
    appReducerBuilder.build(),
    new AppState.loading(),
    new AppActions(),
    middleware: [
      createFirebaseMiddleware(),
    ],
  );
}

middleware

final Firestore firestore = Firestore.instance;

Middleware<AppState, AppStateBuilder, AppActions> createFirebaseMiddleware() {
  return (new MiddlewareBuilder<AppState, AppStateBuilder, AppActions>()
        ..add(AppActionsNames.connectFirestoreAction, connectFirestore))
      .build();
}

connectFirestore(MiddlewareApi<AppState, AppStateBuilder, AppActions> api,
    ActionHandler next, Action<Null> action) {
  firestore
      .collection("menus/P1N09rgDMAgc5u2KrIIT/items")
      .orderBy("sortOrder")
      .snapshots()
      .listen((QuerySnapshot snapshot) {
    BuiltList<MenuItem> menuItems =
        documentsToBuiltList<MenuItem>(snapshot.documents, MenuItem.serializer);
    api.actions.menu.menuItemsLoadedSuccessAction(menuItems);
  });
  next(action);
}

app_state

part 'app_state.g.dart';

abstract class AppState implements Built<AppState, AppStateBuilder> {
  static Serializer<AppState> get serializer => _$appStateSerializer;

  factory AppState([updates(AppStateBuilder b)]) = _$AppState;

  AppState._();

  BuiltList<Shop> get shops;

  @nullable
  MenuState get menuState;

menu_state

part 'menu_state.g.dart';

abstract class MenuState implements Built<MenuState, MenuStateBuilder> {
  static Serializer<MenuState> get serializer => _$menuStateSerializer;

  factory MenuState([updates(MenuStateBuilder b)]) = _$MenuState;

  MenuState._();

  @nullable
  String get id;

  BuiltList<MenuItem> get menuItems;

  @nullable
  String get title;
}

menu_item

part 'menu_item.g.dart';

abstract class MenuItem implements Built<MenuItem, MenuItemBuilder> {
  static Serializer<MenuItem> get serializer => _$menuItemSerializer;

  factory MenuItem([updates(MenuItemBuilder b)]) = _$MenuItem;

  MenuItem._();

  @nullable
  String get currency;

  @nullable
  String get description;

  String get id;

  @nullable
  double get price;

  int get sortOrder;

  String get title;

  int get type;
}

app_actions

part 'app_actions.g.dart';

abstract class AppActions extends ReduxActions {
  ActionDispatcher<Null> connectFirestoreAction;
  ActionDispatcher<BuiltList<Shop>> shopsLoadedSuccessAction;

  factory AppActions() => new _$AppActions();

  AppActions._();

  MenuActions get menu;
}

menu_actions

part 'menu_actions.g.dart';

abstract class MenuActions extends ReduxActions {
  ActionDispatcher<BuiltList<MenuItem>> menuItemsLoadedSuccessAction;

  factory MenuActions() => new _$MenuActions();

  MenuActions._();
}

app_reducer

final appReducerBuilder = new ReducerBuilder<AppState, AppStateBuilder>()
  ..add(AppActionsNames.shopsLoadedSuccessAction, shopsLoadedSuccess)
  ..combineNested<MenuState, MenuStateBuilder>(menuReducerBuilder);

menu_reducer

final menuReducerBuilder =
    new NestedReducerBuilder<AppState, AppStateBuilder, MenuState, MenuStateBuilder>(
        (s) => s.menuState,
        (b) => b.menuState) // maps from the main state object to the nested state
      ..add(MenuActionsNames.menuItemsLoadedSuccessAction, menuItemsLoadedSuccess);

void menuItemsLoadedSuccess(MenuState state, Action<BuiltList<MenuItem>> action,
    MenuStateBuilder builder) {
  builder.menuItems.replace(action.payload);
}

menu_widget

class MenuWidget extends StatefulWidget {
  @override
  MenuWidgetState createState() => MenuWidgetState();
}

class MenuWidgetState extends State<MenuWidget>
    with SingleTickerProviderStateMixin {

// ...

  @override
  Widget build(BuildContext context) {
    return StoreConnection<AppState, AppActions, BuiltList<MenuItem>>(
        connect: (state) => state.menuState.menuItems,
        builder: (BuildContext context, BuiltList<MenuItem> menuItems,
            AppActions actions) {
          print(menuItems); // not printed when nested action triggers nested reducer :(
          return Scaffold(

// ...

            floatingActionButton: FloatingActionButton(
              child: Icon(Icons.control_point),
              onPressed: () {
                actions.connectFirestoreAction();
              },
            ),

// ...
@btastic
Copy link

btastic commented Jun 30, 2018

Did you find a workaround to this?

@davidmarne
Copy link
Owner

see Workiva/built_redux#81

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants