I'm using StateProvider<List<String>> to keep track of user taps on the Tic Tac Toe board. Actual board is a widget that extends ConsumerWidget and consists of tap-able GridView.
Within the onTap event of GridViews child - following is invoked to update the state:
ref.read(gameBoardStateProvider.notifier).state[index] = 'X';
For some reason this does not invoke widget rebuild event. Due to this I cannot see the 'X' in the GridView item which was tapped.
However, if I add additional "simple" StateProvider<int> and invoke it as well within the same onTap event then the widget gets rebuilt and I can see the 'X' in the GridView. I am not even using or displaying this additional state provider but for some reason it invokes rebuild while my intended provided doesn't.
final gameBoardStateProvider = StateProvider<List<String>>((ref) => List.filled(9, '', growable: false));
final testStateProvider = StateProvider<int>((ref) => 0); //dummy state provider
class Board extends ConsumerWidget {
const Board({Key? key}) : super(key: key);
@override
Widget build(BuildContext context, WidgetRef ref) {
final gameBoard = ref.watch(gameBoardStateProvider);
final testState = ref.watch(testStateProvider);
return Expanded(
child: Center(
child: GridView.builder(
itemCount: 9,
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3),
shrinkWrap: true,
itemBuilder: ((BuildContext context, int index) {
return InkWell(
onTap: () {
//With this line only the widget does not get refreshed - and I do not see board refreshed with added 'X'
ref.read(gameBoardStateProvider.notifier).state[index] = 'X';
//??? If I add this line as well - for some reason the widget get refreshed - and I see board refreshed with added 'X'
ref.read(testStateProvider.notifier).state++;
},
child: Container(
decoration: BoxDecoration(border: Border.all(color: Colors.white)),
child: Center(
child: Text(gameBoard[index]),
),
),
);
}),
),
),
);
}
}