I am trying to use riverpod inside my modalBottomsheet to update values, but when i try to update the state, it updates but Widget(FilterView) doesnot rebuild. Since it is Inside of showModalBottomSheet, I have enclosed it inside
ProviderScope()
Below is my code to open ModalBottomSheet
_showFilter(BuildContext context) {
final container = ProviderScope.containerOf(context);
showModalBottomSheet(
context: context,
builder: (context) => ProviderScope(
parent: container,
child: FilterView(
key: Key("filterview"),
),
),
);
}
Below is FilterView Widget
class FilterView extends ConsumerWidget {
const FilterView({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
return Consumer(builder: ((context, ref, _) {
var reference = ref.read(filterController.notifier);
var filter = ref.watch(filterController);
return Card(
child: Column(
children: [
const Text(
"FILTER",
style: TextStyle(fontSize: 30, fontWeight: FontWeight.bold),
),
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Checkbox(
value: filter.today,
onChanged: (bool? value) {
reference.today(value ?? false);
}),
const Text("Today only")
],
),
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
const Text("From Date:"),
IconButton(
onPressed: filter.today
? null
: () async {
var date =
await _showDatePicker(context, filter.fromDate);
reference.newFromDate(date);
},
icon: const Icon(Icons.date_range),
),
if (filter.fromDate != null)
Text(filter.fromDate!.toHumanRedable()),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
const Text("To Date"),
IconButton(
onPressed: filter.today
? null
: () async {
var date =
await _showDatePicker(context, filter.toDate);
reference.newToDate(date);
},
icon: const Icon(Icons.date_range),
),
if (filter.toDate != null)
Text(filter.toDate!.toHumanRedable()),
],
),
ElevatedButton(
onPressed: () {
Navigator.pop(context);
},
child: const Text("Filter with Given Criteria"),
),
],
),
);
}));
}
Future<DateTime?> _showDatePicker(
BuildContext context, DateTime? initialDate) async {
var result = await showDatePicker(
context: context,
firstDate: DateTime.now().add(const Duration(days: -100)),
lastDate: DateTime.now().add(const Duration(days: 100)),
initialDate: initialDate ?? DateTime.now(),
);
return result;
}
}
State does update I have verified that. But FilterView Widget is not rebuilding.
Below is the provider
final filterController =
StateNotifierProvider<FilterNotifier, Filter>((ref) => FilterNotifier());
class FilterNotifier extends StateNotifier<Filter> {
FilterNotifier() : super(Filter.initialize());
void newFromDate(DateTime? fromDateTime) {
state = state.registerNewFromDate(fromDateTime);
}
void newToDate(DateTime? toDateTime) {
state = state.registerNewToDate(toDateTime);
}
void today(bool today) {
state = state.registerNewValues(today, state.fromDate, state.toDate);
}
}
Below is a filter class
class Filter {
bool today = true;
DateTime? fromDate;
DateTime? toDate;
Filter._(this.today, this.fromDate, this.toDate);
static Filter initialize() {
return Filter._(true, null, null);
}
Filter registerNewValues(bool today, DateTime? fromDate, DateTime? toDate) {
this.today = today;
this.fromDate = fromDate;
this.toDate = toDate;
return this;
}
Filter registerNewFromDate(DateTime? fromDate) {
this.fromDate = fromDate;
return this;
}
Filter registerNewToDate(DateTime? toDate) {
this.toDate = toDate;
return this;
}
}
CodePudding user response:
The current model class Filter
having same instance, therefore the UI isn't updating. To update the state, you need to pass new instance. I am creating copyWith method wich is handy,
class Filter { // I pefer creating final fileds with copyWith
bool today = true;
DateTime? fromDate;
DateTime? toDate;
Filter._(this.today, this.fromDate, this.toDate);
static Filter initialize() {
return Filter._(true, null, null);
}
Filter registerNewFromDate(DateTime? fromDate) {
this.fromDate = fromDate;
return this;
}
Filter registerNewToDate(DateTime? toDate) {
this.toDate = toDate;
return this;
}
Filter copyWith(
bool? today,
DateTime? fromDate,
DateTime? toDate,
) {
return Filter._(
today ?? this.today,
fromDate ?? this.fromDate,
toDate ?? this.toDate,
);
}
}