Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Navigator operation requested with a context that does not include a Navigator

Tags:

flutter

People also ask

What is navigator of context?

Navigator. of(context) has optional parameters, if rootNavigator is set to true, the NavigatorState from the furthest is given instead. static NavigatorState of( BuildContext context, { bool rootNavigator = false, bool nullOk = false, }) Navigator. push(context, route) is a static method and do both at the same time.

What is a navigator and what are routes in Flutter?

Route: A Route is an abstraction for a “screen” or “page” of an app, and a Navigator is a widget that manages routes. Navigator: Creates a widget that maintains a stack-based history of child widgets. A Navigator can push and pop routes to help a user move from screen to screen.

How do you get the navigator back in Flutter?

Pressing the device back button (Android only) will navigate the user back to the first page. It does this by popping the route off the stack maintained by the Navigator.


TLDR: Wrap the widget which needs to access to Navigator into a Builder or extract that sub-tree into a class. And use the new BuildContext to access Navigator.


This error is unrelated to the destination. It happens because you used a context that doesn't contain a Navigator instance as parent.

How do I create a Navigator instance then ?

This is usually done by inserting in your widget tree a MaterialApp or WidgetApp. Although you can do it manually by using Navigator directly but less recommended. Then, all children of such widget can access NavigatorState using Navigator.of(context).

Wait, I already have a MaterialApp/WidgetApp !

That's most likely the case. But this error can still happens when you use a context that is a parent of MaterialApp/WidgetApp.

This happens because when you do Navigator.of(context), it will start from the widget associated to the context used. And then go upward in the widget tree until it either find a Navigator or there's no more widget.

In the first case, everything is fine. In the second, it throws a

Navigator operation requested with a context that does not include a Navigator.

So, how do I fix it ?

First, let's reproduce this error :

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Center(
        child: RaisedButton(
          child: Text("Foo"),
          onPressed: () => Navigator.pushNamed(context, "/"),
        ),
      ),
    );
  }
}

This example creates a button that attempts to go to '/' on click but will instead throw an exception.

Notice here that in the

  onPressed: () => Navigator.pushNamed(context, "/"),

we used context passed by to build of MyApp.

The problem is, MyApp is actually a parent of MaterialApp. As it's the widget who instantiate MaterialApp! Therefore MyApp's BuildContext doesn't have a MaterialApp as parent!

To solve this problem, we need to use a different context.

In this situation, the easiest solution is to introduce a new widget as child of MaterialApp. And then use that widget's context to do the Navigator call.

There are a few ways to achieve this. You can extract home into a custom class :

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: MyHome()
    );
  }
}

class MyHome extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Center(
        child: RaisedButton(
          child: Text("Foo"),
          onPressed: () => Navigator.pushNamed(context, "/"),
        ),
      );
  }
}

Or you can use Builder :

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Builder(
        builder: (context) => Center(
              child: RaisedButton(
                child: Text("Foo"),
                onPressed: () => Navigator.pushNamed(context, "/"),
              ),
            ),
      ),
    );
  }
}

Hy guys, i have the same problem. This is occur for me. The solution what i found is very simple. Only what i did is in a simple code:

void main() {
  runApp(MaterialApp(
    home: YOURAPP() ,
    ),
  );
}

I hope was useful.


Make sure your current parent widget not with same level with MaterialApp

Wrong Way

class HomeScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          centerTitle: true,
          title: Text('Title'),
        ),
        body: Center(
            child: Padding(
          padding: EdgeInsets.symmetric(vertical: 8.0, horizontal: 16.0),
          child: RaisedButton(
              onPressed: () {
                //wrong way: use context in same level tree with MaterialApp
                Navigator.push(context,
                    MaterialPageRoute(builder: (context) => ScanScreen()));
              },
              child: const Text('SCAN')),
        )),
      ),
    );
  }
}

Right way

void main() => runApp(MaterialApp(
      title: "App",
      home: HomeScreen(),
    ));

class HomeScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        centerTitle: true,
        title: Text('Title'),
      ),
      body: Center(
          child: Padding(
        padding: EdgeInsets.symmetric(vertical: 8.0, horizontal: 16.0),
        child: RaisedButton(
            onPressed: () {
            //right way: use context in below level tree with MaterialApp
              Navigator.push(context,
                  MaterialPageRoute(builder: (context) => ScanScreen()));
            },
            child: const Text('SCAN')),
      )),
    );
  }
}

I set up this simple example for routing in a flutter app:

import 'package:flutter/material.dart';

void main() {
  runApp(new MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Flutter Demo',
      home: new MyHomePage(),
      routes: <String, WidgetBuilder>{
        '/settings': (BuildContext context) => new SettingsPage(),
      },
    );
  }
}

class MyHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text('TestProject'),
      ),
      body: new Center(
        child: new FlatButton(
          child: const Text('Go to Settings'),
          onPressed: () => Navigator.of(context).pushNamed('/settings')
        )
      )
    );
  }
}

class SettingsPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new Scaffold(
        appBar: new AppBar(
          title: new Text('SettingsPage'),
        ),
        body: new Center(
            child: new Text('Settings')
        )
    );
  }
}

Note, that the SettingsPage extends StatelessWidget and not Navigator. I'm not able to reproduce your error.

Does this example help you in building your app? Let me know if I can help you with anything else.