Cody Moore
Cody Moore

Reputation: 61

Riverpod not reloading consumer widget until hot reload

I'm having trouble getting Riverpod to notify state changes. I am new to Riverpod, so it is possible I'm misunderstanding how it works.

I want to use Riverpod to provide an object variable that I set information in on another widget tree before providing the information in that class to a consumer in a separate widget tree. This consumer functionally acts as a sort of window fragment, where I want to place a specific widget, determined by the information in the provided object, in this section of the screen.

Here is the Provider I have set up for the object.

final userPageContext = StateProvider<UserPageContext>((ref) {
  return UserPageContext(ptContext: PageTypes.WELCOME);
});

Here is the consumer I have watching for state changes before displaying a specific widget.

Consumer(
                builder: (context, ScopedReader watch, __) {
                  final pageContext = watch(userPageContext).state;
                  return getPageToDisplay(pageContext);
                },
              ),

This function provides the widget to be shown.

  Widget getPageToDisplay(UserPageContext pageContext) {
    if (pageContext.entryReady) {
      return EntryScreen(entry: pageContext.getNewEntry());
    } else {
      return Container();
    }
  }

Here is the build method in which I change the states of the provided object.

@override
  Widget build(BuildContext context) {
    return Consumer(builder: (_, ScopedReader watch, __) {

      final pageContext = watch(userPageContext).state;

      return Dialog(
        ... widgets ...
                Row(
                  ... widgets ...
                        // A button press confirms the users choice and then submits it to the provider
                        onPressed: () {
                          Entry entry = Entry(
                              entryType: entryType,
                              id: id,
                              name: name);

                          pageContext.ptContext = PageTypes.ENTRY;
                          pageContext.setNewEntry(entry);
                          pageContext.entryReady = true;

                          // These pops remove dialog menus that were in the current widget branch
                          Navigator.of(context).pop();
                          Navigator.of(context).pop();
                        },
                        ... widgets ...
                        ),
                      ),
                    )
                  ],
                )
              ],
            ),
          ),
        ),
      );
    });
  }

Here is the class that is meant to store the state information.

class UserPageContext {
  UserPageContext({required this.ptContext});

  late Entry _newEntry;
  bool entryReady = false;

  /// sets new entry and flags the class state to ready for listeners
  void setNewEntry(Entry entry) {
    _newEntry = entry;
    entryReady = true;
  }

  Entry getNewEntry() {
    entryReady = false;
    return _newEntry;
  }

  PageTypes ptContext;
}

I have tried a number of different variations in which way I call the provider, from context.read and watch to watch(object.notifier) and watch(object.notifier).state. I think I have tried the majority of those possibilities, so I am unsure if that could be the cause of my issue.

-- Small Edit -- I forgot to add that proceeding through the logic seems to work fine, but the state does not update until I perform a hot reload. The intended page then appears. Oddly enough, though, the page disappears immediately after another hot reload. This seems to suggest that either the information I am giving to the provider is being rewritten immediately after use, or I am somehow not changing the provider? I am unsure, to be honest.

Thank you in advance, and I hope you have a great day!

Upvotes: 2

Views: 1480

Answers (1)

Cody Moore
Cody Moore

Reputation: 61

I seem to have solved the problem. I tried using a ChangeNotifierProvider once again. Using this in tandem with an extended ChangeNotifier, and making sure to NotifyListeners at the proper time, seemed to do the trick.

Here is the Provider I ended up using.

final userPageContext = ChangeNotifierProvider((ref) {
  return UserPageContext(ptContext: PageTypes.WELCOME);
});

These are the changes I made to the class.

class UserPageContext extends ChangeNotifier {

  /// sets new entry and flags the class state to ready for listeners
  void setNewEntry(Entry entry) {
    ... code ...
    notifyListeners();
  }
 ...

Finally, one of the issues I ran into when first trying ChangeNotifier was that it didn't seem to have a state access, similar to the syntax of many other providers used with Riverpod. It turns out that you don't need that, because it simply returns the object you're looking for when you watch it. Here is how I called the provider.

final pageContext = watch(userPageContext);

Upvotes: 0

Related Questions