I have a list of todo elements managed by:
@Riverpod(keepAlive: true)
class TodosNotifier extends _$TodosNotifier {
@override
List<Todo> build() {
return [.....some elements here.....];
}
void addTodo(Map<String, Object?> todoJson) {
Todo todo = Todo.fromJson(todoJson);
state = [...state, todo];
}
...other methods here that change the state for different reasons...
}
and I have another Notifier
which is meant to change its value only when the size of the TodosNotifier
list changes (via addTodo(...)
).
@Riverpod(keepAlive: true)
class TodosLengthNotifier extends _$TodosLengthNotifier {
@override
int build() => 0;
void update() {
// it never gets called here
List<Todo> todos = ref.watch(todosNotifierProvider);
if (state != todos.length) {
state = todos.length;
}
}
}
The problem is that the method TodosLengthNotifier.update()
never gets called every time I add a new "todo" element with TodosNotifier.addTodo()
. How can I fix that?
UPDATE
Based on the given answer I am now just using:
@Riverpod(keepAlive: true)
int todosLength(TodosLengthRef ref) => ref.watch(todosNotifierProvider).length;
Any custom methods you define inside a notifier won't get called unless you explicitly call it. For example, to call the update
method, you would do:
ref.read(todosNotifierProvider.notifier).update();
But what you want here is that the value exposed by todosLengthNotifierProvider
to be reactive to the changes from TodosNotifier
. In order to do that, you should watch TodosNotifier
inside the build
method of TodosLengthNotifier
. The returned value should be the value that you want this notifier to expose.
@Riverpod(keepAlive: true)
class TodosLengthNotifier extends _$TodosLengthNotifier {
@override
int build() {
List<Todo> todos = ref.watch(todosNotifierProvider);
return todos.length;
}
}
Now when the list from TodosNotifier
changes, the build
method of TodosLengthNotifier
will be executed again so the value exposed by todosLengthNotifierProvider
will change as well.
Furthermore, if you're not going to introduce side-effect methods to TodosLengthNotifier
(and probably makes more sense that way, since it's just exposing a "computed" property from another provider), you'd better off using a regular Provider
instead.