2

So I have an InheritedWidget which holds a token.

class TokenHolder extends InheritedWidget {
  final String token;

  const TokenHolder({@required this.token, @required Widget child})
      : assert(child != null),
        super(child: child);

  @override
  bool updateShouldNotify(TokenHolder oldWidget) => oldWidget.token != token;

  static TokenHolder of(BuildContext context) {
    return context.dependOnInheritedWidgetOfExactType<TokenHolder>();
  }
}

Then somewhere high up in my app, I have used it to display MyScreen

...
builder: (context) {
  ...
  return TokenHolder(
     token: token,
     child: MyScreen(),
  );
}

MyScreen works as expected. It can get the TokenHolder´s token correctly.

class MyScreen extends StatefulWidget {
  @override
  _MYyScreenState createState() => _MYyScreenState ();
}

class _MYyScreenState extends State<MyScreen > {
  @override
  Widget build(BuildContext context) {
    String token = TokenHolder.of(context).token; // This works

    return RaisedButton(
      onPressed: () {
        Navigator.push(context, builder: (context) => PushedScreen());
      },
      child: Text(token) // This works
    );
  }
}

However, PushedScreen seems to return null when we call TokenHolder.of(context). Why is this? Why cannot the TokenHolder be found?

class PushedScreen extends StatefulWidget {
  @override
  _PushedScreenState createState() => _PushedScreenState ();
}

class _PushedScreenState extends State<PushedScreen > {
  @override
  Widget build(BuildContext context) {
    String token = TokenHolder.of(context).token; // DOES NOT WORK -> null.token

    return Text(token);
  }
}
Magnuti
  • 63
  • 9

1 Answers1

0

Instead of accessing the token using "TokenHolder.of(context).token", you could pass the token as an argument when you push the route. (I don't know if it's required to use pushNamed, but that's what I use)

Navigator.pushNamed(
    context,
    '/pushedScreen', 
    arguments: token
);

Then to get the token in PushedScreen either use:

MaterialApp(
    onGenerateRoute: (settings) { 
        //only needed if their are multiple screens
        if (settings.name == '/pushedScreen') {
            String token = settings.arguments;
        } 
    }
    
)

You can also try (within pushedScreen)

@override
Widget build(BuildContext context) {
    String token = ModalRoute.of(context).settings.arguments;
}

To use pushNamed:

MaterialApp(
    ...
    initialRoute: '/',
    routes {
        '/': (context) => ARoute(),
        '/pushedScreen': (context) => PushedScreen(),
    }
)
Eli Front
  • 695
  • 1
  • 8
  • 28
  • 1
    Yeah that sounds like a simple solution, but the whole point of using InheritedWidget is avoid passing props down to every child. My `PushedRoute` pushes a new route, which needs the token, so this is not the solution I am after. – Magnuti Jul 31 '20 at 08:47