I am using Riverpod and have set up a Provider and Notifier for my data, however when I modify the data in the provider, my UI is not reflecting that change. If I save and hot-reload my app, the new values are shown.
For context, my Board contains a property that is a Map of Players and their Scores. On my Board screen, I am iterating through a list conversion of the 'boardData' map for a GridView.builder, like so:
ref.read(boardProvider.notifier).loadBoard(widget.board); final providedBoard = ref.watch(boardProvider); List<MapEntry<PlayerModel, int>> boardDataList = providedBoard.boardData.entries.toList(); body: GridView.builder( padding: const EdgeInsets.all(16), gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 2, childAspectRatio: 3 / 2, //1.5 crossAxisSpacing: 10, mainAxisSpacing: 10, ), itemCount: providedBoard.boardData.length, itemBuilder: (context, index) => BoardPlayerGridItem( player: boardDataList[index].key, score: boardDataList[index].value, ), ),
Here is my provider:
class BoardNotifier extends StateNotifier<BoardModel> { BoardNotifier() : super(sampleBoard); // Load the currently viewed board into notifier loadBoard(BoardModel board) { state = board; } // Update the player's score in the board by the configured increment incrementPlayerScore(BoardModel board, PlayerModel player) { board.boardData.update(player, (value) => value + board.increment); // Update our board in state state = board; }}final boardProvider = StateNotifierProvider<BoardNotifier, BoardModel>((ref) { return BoardNotifier();});
Here is my BoardPlayerGridItem (the widget in the GridView) that is not updating.
class BoardPlayerGridItem extends ConsumerStatefulWidget { const BoardPlayerGridItem({ super.key, required this.player, required this.score, }); final PlayerModel player; final int? score; @override ConsumerState<ConsumerStatefulWidget> createState() => _BoardPlayerGridItemState();}class _BoardPlayerGridItemState extends ConsumerState<BoardPlayerGridItem> { @override Widget build(BuildContext context) { final providedBoard = ref.watch(boardProvider); return GestureDetector( onTap: () { ref.watch(boardProvider.notifier).incrementPlayerScore( providedBoard, widget.player, ); }, onLongPress: () {}, // Open edit form child: Container( color: Theme.of(context).highlightColor, child: Column( crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center, children: [ Text( widget.player.name, style: Theme.of(context) .textTheme .titleMedium! .copyWith(color: Theme.of(context).colorScheme.onBackground), ), const SizedBox(height: 10), Text( widget.score.toString(), style: Theme.of(context) .textTheme .displayLarge! .copyWith(color: Theme.of(context).colorScheme.onBackground), ), ], ), ), ); }}
The UI is a grid of tiles and tapping on each increments the counter. I thought by adding watching my boardProvider and then changing it as per the onTap function, that would prompt the rebuild, but seems not. Any pointers appciated.