Reputation: 11
I've got this simple Homepage
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Row(
children: [
MyDrawer(),
selectWindow(),
],
),
),
);
}
and
class MyDrawer extends ConsumerStatefulWidget {
MyDrawer({super.key});
@override
ConsumerState createState() {
return _MyDrawerState();
}
}
class _MyDrawerState extends ConsumerState<MyDrawer> {
@override
Widget build(BuildContext context) {
final myProvider = ref.watch(myProviderProvider);
return Drawer(
shape: const ContinuousRectangleBorder(),
width: 300,
child: Text(
myProvider.length.toString(),
style: const TextStyle(fontSize: 24),
),
);
}
my IDE suggests that i use const in these spots
const MyDrawer({super.key});
and
body: Center(
child: Row(
children: [
//HERE
const MyDrawer(),
selectWindow(),
],
),
),
but when I do add the const as suggested the state does not changes when the myProvider.length changes. I have to manually refresh so the length change appears.
Am I doing anything wrong or the IDE suggests something wrong?
Upvotes: 0
Views: 119
Reputation: 1326
Not sure what you mean by manually refresh
. I suspect the issue has to do with the fact that you have used an AutoDisposeNotifierProvider
. You could check the type of the object myProviderProvider
.
With myProviderProvider
the build
method is called whenever the page is accessed, and previous changes are overwritten.
I have used the provider below (notice the option keepAlive
). With this option listSelectorProvider
will be of type NotifierProvider
.
The random list entries are just used to see if the build method was called or not.
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
part 'list_selector.g.dart';
final random = Random();
@Riverpod(keepAlive: true)
class ListSelector extends _$ListSelector {
@override
List<int> build() {
return [random.nextInt(100), random.nextInt(100)];
}
void add(int value) {
state.add(value);
}
void set(List<int> value) {
state = value;
}
}
There is little benefit in using a ConsumerStatefulWidget
unless you store a local state variable and are calling the setState
function.
I used this drawer and it works like expected:
class MyDrawer extends ConsumerWidget {
const MyDrawer({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
final list = ref.watch(listSelectorProvider);
return Drawer(
shape: const ContinuousRectangleBorder(),
width: 300,
child: Text(
list.length.toString(),
style: const TextStyle(fontSize: 24),
),
);
}
}
To change the state of listSelectorProvider
I have used the class below.
Notice the const
keyword before MyDrawer
.
class HomePage extends ConsumerWidget {
const HomePage({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
return Scaffold(
appBar: AppBar(
title: const Text('Home Page'),
),
drawer: const MyDrawer(),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'Starting page' + ref.watch(listSelectorProvider).toString(),
),
Text(
'Press + to change the list. ',
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
final list = ref.watch(listSelectorProvider);
ref.read(listSelectorProvider.notifier).add(101);
},
child: const Icon(Icons.add),
),
);
}
}
Upvotes: 0