It's a simple ToDo app with a login feature using appwrite as the backend. The problem is that when I log in, I do a ref.read to the method and it download the user tasks but when its logged and have to go directly to the task screen it uses a ref.watch where the build don't do the call to the backend.
Is it okay to make a call to a backend in the build() of a NotifierProvider?
void main() {
runApp(const ProviderScope(child: MainApp()));
}
class MainApp extends ConsumerWidget {
const MainApp({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
return MaterialApp(
theme: ThemeData(useMaterial3: true),
// home: user.$id? LoginForm() : const ToDoScreen(),
home: ref.watch(appwriteExistingUserProvider).when(
data: (user) {
if (user != null) {
return const ToDoScreen();
}
return LoginForm();
},
error: (error, st) => Text(error.toString()),
loading: () => const Center(child: CircularProgressIndicator()),
),
);
}
}
@Riverpod(keepAlive: true)
class TodoController extends _$TodoController {
@override
TodoState build() {
return const TodoState(todosMap: <String, ToDoModel>{
'1': ToDoModel(task: "task", documentId: "documentId")
}, loading: true);
}
Future<void> getTodos() async {
TodoRepository todoRepository = TodoRepository(ref);
state = state.copyWith(loading: true);
try {
final todos = await todoRepository.getTodos();
state = state
.copyWith(todosMap: {for (ToDoModel v in todos) v.documentId: v});
} finally {
state = state.copyWith(loading: false);
}
}
}
Yes, you need to do this in the build
method. However, your provider will then become an AsyncNotifier
and the state will become Future<TodoState>
. There will be no recalls during rebuilds (or you can make a timer), since you are using state caching via @Riverpod(keepAlive: true)
.