0

have a problem that I'm sitting on couple of days now. have an app where:

  • depending of AUTH state, 'LoginScreen' or 'MainScreen' is Shown.

  • in MainScreen I setUp bottomNavigation with screens (HomeScreen, ShoppingScreen,MyFavorites)

  • I set up there as well my StreamProviders(those depend on Auth) by using MultiProvider
  • on HomeScreen when I User Provider.of(context) it works like it should
  • but when I use :

    `Navigator.push(
      context,
      MaterialPageRoute(
        builder: (_) => ProfileScreen(),
      ),
    );
    

` and use Provider.of(context) there I get "Could not find correct Provider....above this...widget"

I read some issues on that and solution there was to decler providers above MaterailApp which in my case I can not do because I can set up thoese only after Auth is successfull.

Tryed passing context(from HomeScreen) to ProfileScreen(through constructor) and that work but when value changed of UserData it did not update the screen (guessing beacause of diffrent 'contexts')

What am I doing wrong in here,any Ideas?:S

pb4now
  • 1,305
  • 4
  • 18
  • 45

2 Answers2

3

Providers are "scoped".

This means that if they are placed inside a screen, they aren't accessible outside that screen.

Which means that if a provider is scoped but needs to be accessed outside of the route it was created in, we have two solutions:

  • un-scope the provider. This involves moving the provider to a common ancestor of both widgets that needs to obtain the value.

    If those two widgets are on two different Routes, then it basically mean "move the provider above MaterialApp/CupertinoApp.

  • manually pass the provider to the new screen (needed when using Navigator.push)

    The idea is, instead of having one provider, we have two of them, both using the same value as explained here See How to scope a ChangeNotifier to some routes using Provider? for a practical example.

    For Navigator.push, this can look like:

    final myModel = Provider.of<MyModel>(context);
    Navigator.push(
      context,
      MaterialPageRoute(
        builder: (_) =>
          ChangeNotifierProvider.value(
            value: myModel,
            child: MyScreen(),
        ),
      ),
    );
    
Rémi Rousselet
  • 256,336
  • 79
  • 519
  • 432
  • TY very much @Remi perfect information - would like to give you checkmark as well because both you and Kushagra answers helped me alot so I'm just going with the one that was first:S – pb4now Oct 13 '19 at 07:43
1

Please make sure that you application's root widget is Provider Widget, it should event be the parent of MaterialWidget. If this is already the case I will need your code to look into. Something like this

class AppState {
 User loggedInUser;

 bool get isLoggedIn {
  return loggedInUser != null;
 }

 // Other states as per the requirements
 // ...
}
Kushagra Saxena
  • 671
  • 5
  • 17
  • Hi, no it's not -So U correct there - but I have StreamProviders that can not be declare in applications root i.e "Stream" that can be added as a provider after AUTH is successfull which means that it will not be declared in applications root... how do I tackle that ?: – pb4now Oct 08 '19 at 11:52
  • 1
    In this case I think your application should expose a root state which should contain all subsequent states in it like `loggedInUser`, `Posts` etc. (as per use case) from a parent StreamProvider above the MaterialWidget and till the user has not signed up the `auth` or `loggedInUser` key can be null. – Kushagra Saxena Oct 08 '19 at 11:56
  • it's like I understand but still I do not...:). Do U mean I should have two separate Material Widgets for each state of Auth?-or am I miss understanding everything?:S – pb4now Oct 08 '19 at 14:23
  • No you won't have two Material widgets but to put simply the above explanation. Keep the StreamProvider at the root of all like I mentioned its just that till the user is not authenticated the values will be null and after the user logs in update those values in the state. – Kushagra Saxena Oct 08 '19 at 14:25
  • hmmm I think*I understand (and by that I mean : I hope that I understand:)) - I'll give it a try comeback to you and of course mark your answer (maybe tomorrow although -away from the computer atm) thank you for your time/help – pb4now Oct 08 '19 at 14:31
  • Sure let me know if you face any issues. Thanks :) – Kushagra Saxena Oct 08 '19 at 15:22
  • worked like a charm:) could U just update your answer and implement the answer U gave in comment("In this case ...") so that I can accept as an answer. (sorry for late answer) – pb4now Oct 13 '19 at 07:39
  • @pb4now I have updated the answer please let me know if you need something else. – Kushagra Saxena Oct 14 '19 at 08:17