Reputation: 127
I am trying to retrieve and delete a TodoList using flutter_riverpod's stateNotifierProvider. In the code below, the fetchTodoList method works fine, but the deleteTodoList method does not work.
UI
class TodoList extends ConsumerWidget {
@override
Widget build(BuildContext context, ScopedReader watch) {
final todoAsyncValue = watch(todoFutureProvider);
return Padding(
padding: const EdgeInsets.all(8),
child: todoAsyncValue.when(
data: (todoList) => SingleChildScrollView(
child: Scaffold(
body: Column(
children: _buildTodoList(todoList),
),
floatingActionButton: FloatingActionButton(
onPressed: context.read(todoNotifierProvider.notifier).deleteTodoList(),
child: const Icon(Icons.delete),
),
),
),
loading: () => const Center(child: const CircularProgressIndicator()),
error: (error, stack) => Text(error.toString()),
),
);
}
_buildTodoList(){ // ......}
}
Provider & Class
final todoNotifierProvider = StateNotifierProvider<TodoListStateNotifier, List<Todo>>((ref) {
return TodoListStateNotifier();
});
final todoFutureProvider = FutureProvider<List<Todo>>((ref) async {
final todo= ref.read(todoNotifierProvider.notifier);
await todo.fetchTodoList();
return ref.watch(todoNotifierProvider);
});
class TodoListStateNotifier extends StateNotifier<List<Todo>>{
TodoListStateNotifier(): super([]);
Future<void> fetchTodoList() async {
final todoClient = TodoClient();
state = await todoClient.fetchTodoList();
}
void deleteTodoList() {
var list = <Todo>[];
list = state.removeLast();
state = list;
}
}
The following error message is displayed.
A value of type 'Todo' can't be assigned to a variable of type 'List'.
Also, if I convert the code to the following, the error is not displayed, but it is not reflected in the UI properly.
void deleteTodoList() {
state.removeLast();
}
I am assuming that the type defined in the following code is the type of the state, am I wrong?
class TodoListStateNotifier extends StateNotifier<List<Todo>>{
Is it not possible to read the state in the code?
Please let me know if you know a better way.
Upvotes: 0
Views: 531
Reputation: 189
Every time when the UI rebuilds, the function is called. The error is here:
onPressed: context.read(todoNotifierProvider.notifier).deleteTodoList(),
you can remove the ()
or you can write:
onPressed: () => context.read(todoNotifierProvider.notifier).deleteTodoList(),
Upvotes: 0
Reputation: 5743
Here the removeLast()
method returns a Todo
exactly the last Todo
in the list that's the why of the error
A value of type 'Todo' can't be assigned to a variable of type 'List'
Because you are indeed trying to assign a Todo to a List.
void deleteTodoList() {
var list = <Todo>[];
list = state.removeLast();
state = list;
}
Now with the second example, here you effectively remove the last item but don't emit a new state, thus the UI does not rebuild.
void deleteTodoList() {
state.removeLast();
}
Alternatives:
state = state.where((todo) => todo.id != target.id).toList()
void deleteTodoList() {
var list = <Todo>[];
state.removeLast();
list=state;
state = list;
}
Use the spread operator(...) to make a copy of the list and the cascade operator for the applied method not to return the removed item.
void deleteTodoList() {
state=[...state..removeLast()];
}
Upvotes: 1