Search code examples
flutterdart

Using Navigator in initState


I have a loading screen in which I request some endpoints(API call) and then I want to push to the HomePage

when I call Navigator.push function I get this error:

Unhandled Exception: Navigator operation requested with a context that does not include a Navigator. E/flutter ( 5168): The context used to push or pop routes from the Navigator must be that of a widget that is a descendant of a Navigator widget.

I have tried wrapping it in WidgetsBinding.instance.addPostFrameCallback((_) as well as added delay of one second before navigating

code snippet:

@override
void initState(){
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) {
   loadData();
});

void loadData() async {
await MyHttpRequests
await Future.delayed(Duration(seconds: 1));
Navigator.pushReplacement(
  context,
  PageRouteBuilder(
    pageBuilder: (context, animation, secondaryAnimation) =>
        const HomePage(),
    transitionsBuilder: (context, animation, secondaryAnimation, child) {
      return child;
    },
    transitionDuration: const Duration(milliseconds: 0),
  ));
}

Solution

  • Example Solution Wrap your navigation logic in a widget that has access to a Navigator: Ensure that the context you use for navigation is within the widget tree where a Navigator is present.

    Use a FutureBuilder to handle the loading state and navigation.

    Updated Code Here’s how you can update your initState method and handle navigation correctly:

    import 'package:flutter/material.dart';
    
    class LoadingScreen extends StatefulWidget {
      @override
      _LoadingScreenState createState() => _LoadingScreenState();
    }
    
    class _LoadingScreenState extends State<LoadingScreen> {
      @override
      void initState() {
        super.initState();
        WidgetsBinding.instance.addPostFrameCallback((_) {
          loadData();
        });
      }
    
      Future<void> loadData() async {
        await MyHttpRequests(); // Replace with your actual HTTP request
        await Future.delayed(Duration(seconds: 1)); // Simulate some delay
    
        // Ensure the navigation happens in the context of this widget's subtree
        if (mounted) {
          Navigator.pushReplacement(
            context,
            PageRouteBuilder(
              pageBuilder: (context, animation, secondaryAnimation) => HomePage(),
              transitionsBuilder: (context, animation, secondaryAnimation, child) {
                return child;
              },
              transitionDuration: const Duration(milliseconds: 0),
            ),
          );
        }
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          body: Center(
            child: CircularProgressIndicator(), // Your loading indicator
          ),
        );
      }
    }
    
    class HomePage extends StatelessWidget {
      const HomePage();
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(title: Text('Home Page')),
          body: Center(child: Text('Welcome to the Home Page!')),
        );
      }
    }