5

I was hoping to use InheritedWidget at the root level of my Flutter application to ensure that an authenticated user's details are available to all child widgets. Essentially making the Scaffold the child of the IW like this:

@override
Widget build(BuildContext context) {
return new AuthenticatedWidget(
    user: _user,
    child: new Scaffold(
      appBar: new AppBar(
        title: 'My App',
      ),
      body: new MyHome(),
      drawer: new MyDrawer(),
    ));
}

This works as expected on app start so on the surface it seems that I have implemented the InheritedWidget pattern correctly in my AuthenticatedWidget, but when I return back to the home page (MyHome) from elsewhere like this:

Navigator.popAndPushNamed(context, '/home');

This call-in the build method of MyHome (which worked previously) then results in authWidget being null:

final authWidget = AuthenticatedWidget.of(context);

Entirely possible I'm missing some nuances of how to properly implement an IW but again, it does work initially and I also see others raising the same question (i.e. here under the 'Inherited Widgets' heading).

Is it therefore not possible to use a Scaffold or a MaterialApp as the child of an InheritedWidget? Or is this maybe a bug to be raised? Thanks in advance!

KBDrums
  • 515
  • 1
  • 6
  • 7

2 Answers2

16

MyInherited.of(context) will basically look into the parent of the current context to see if there's a MyInherited instantiated.

The problem is : Your inherited widget is instantiated within the current context.

=> No MyInherited as parent

=> crash

The trick is to use a different context. There are many solutions there. You could instantiate MyInherited in another widget, so that the context of your build method will have a MyInherited as parent.

Or you could potentially use a Builder to introduce a fake widget that will pass you it's context.

Example of builder :

return new MyInheritedWidget(
  child: new Builder(
    builder: (context) => new Scaffold(),
  ),
);

Another problem, for the same reasons, is that if you insert an inheritedWidget inside a route, it will not be available outside of this route.

The solution is simple here ! Put your MyInheritedWidget above MaterialApp.

above material :

new MyInherited(
  child: new MaterialApp(
    // ...
  ),
)
Rémi Rousselet
  • 256,336
  • 79
  • 519
  • 432
  • Thanks so much @Darky! Some great insight here. The confusion here for me is still that it **does** work the first run and not after future navigation. If I had the parent / current thing wrong we wouldn't expect it to work at all yes? An interesting point made [here](https://medium.com/@mehmetf_71205/inheriting-widgets-b7ac56dbbeb1) that says _... when you use Navigator.push to display these pages, they do not inherit the widget carrying parent’s context._ That seems to really pinpoint my issue and is likely related to what you're saying too, I'll keep digging. Thanks again. – KBDrums Mar 20 '18 at 14:38
  • 1
    Navigator routes are unrelated to each others. They have the same base : MaterialApp and it's parents. But that's it. – Rémi Rousselet Mar 20 '18 at 14:44
  • @KBDrums, feel free to accept Darky's answer if this was what you were looking for – Ashton Thomas Mar 21 '18 at 14:20
1

Is it therefore not possible to use a Scaffold or a MaterialApp as the child of an InheritedWidget?

It is very possible to do this. I was struggling with this earlier and posted some details and sample code here.

You might want to make your App-level InheritedWidget the parent of the MaterialApp rather than the Scaffold widget.

I think this has more to do with how you are setting up your MaterialWidget, but I can't quite tell from the code snippets you have provided.

If you can add some more context, I will see if I can provide more.

Ashton Thomas
  • 16,659
  • 5
  • 31
  • 25
  • Thanks Ashton! Great thoughts and examples. In the end I believe this is turning out to be an issue with trying to use Inherited Widgets across routes as per the discussion with Darky above. Cheers! – KBDrums Mar 20 '18 at 14:49
  • 1
    @KBDrums great! Perhaps the linked example will give you some ideas on structuring InheritedWidget above the route/material app so you can keep that constant – Ashton Thomas Mar 20 '18 at 15:00
  • 2
    @AshtonThomas The link you provided in your answer is dead. Please provide the actual content in your answer. – HBG Aug 08 '18 at 22:53