Riverpod's reference-based system seems to work like a global in a specific case. What am I doing wrong?

707

Remi answered me on Reddit. The solution was to use ScopedProvider for the data, and ProviderScope in the custom widget:

final isTrashView = ScopedProvider<bool>((_) => false);

class MyCustomWidget extends StatelessWidget {
  const MyCustomWidget({this.trashView = false});

  final bool trashView;

  @override
  Widget build(BuildContext context) {
    return ProviderScope(
      overrides: [
        isTrashView.overrideWithValue(trashView),
      ],
      child: AnotherCustomWidget(),
    );
  }
}

class AnotherCustomWidget extends ConsumerWidget { 
   const AnotherCustomWidget({Key? key}) : super(key: key);
   
   @override
   Widget build(BuildContext context, ScopedReader watch) {
     final trashView = watch(isTrashView);
     // etc.
   }
}

Share:
707
Itsastickup
Author by

Itsastickup

Updated on December 29, 2022

Comments

  • Itsastickup
    Itsastickup over 1 year

    Is this a case where I should be using a traditional (pre-riverpod) widget-based provider or does riverpod have a solution for the following scenario?

    I have a 'page' Widget with a listview of items. I instantiate this page class/Widget in two tabs, one for live items and the other as a trash/bin.

    Currently I'm passing an 'is_trash' boolean through the constructor of each instantiation and also the constructors of many custom sub-widgets so they can know to grey things out etc.

    A provider is the obvious way to avoid messing with constructors just for one boolean.

    So the traditional way is :

    
    class MyPage extends StatelessWidget{
       bool isTrashView;
       
       MyPage(this.isTrashView);
       
       Widget build(context){
          return Provider<bool>.value(
             value : isTrashView,
             child : MyCustomList(/*don't need an isTrashView parameter here*/),      
          );
       }
    
    }
    
    class MyCustomList extends StatelessWidget{
    
       Widget build(context){
           bool isTrashView=Provider<bool>.of(context).value;
           return &etc........
    
       }
    
    }
    
    

    ...and each instance of the MyPage widget gets its own unique provider.

    Since riverpod uses globals for the providers, I can't set up unique providers in the two page instances to be read by some sub-widget as they would be sharing the provided variable and overwriting each other's data.

    (I realise I've been a touch verbose: I'm trying to be clear for other beginners to riverpod stumbling across this thread.)

    • Alex Hartford
      Alex Hartford almost 3 years
      I'm not totally sure I completely understand the question but have you looked at the family modifier? riverpod.dev/docs/concepts/modifiers/family
    • Itsastickup
      Itsastickup almost 3 years
      Thanks for trying to help. I've edited the text to try to clarify. I can't see how the family modifier helps.
    • Alex Hartford
      Alex Hartford almost 3 years
      I find this question hard to answer because I'd simply pass isTrashView as a parameter to the child widget.
    • Itsastickup
      Itsastickup almost 3 years
      I would also just do a parameter, but the code-base has a lot of custom Widgets deeply nested, so that's a lot of constructor parameters, and only for a few UI tweaks. I was looking for a better/elegant solution. Remi answred me on Reddit, and what I needed was a ProviderScope with a ScopeProvider for the data.
    • 10 Rep
      10 Rep almost 3 years
      Please add an answer as an answer and not in your question.
  • Alex Hartford
    Alex Hartford almost 3 years
    It would be valuable to add the implementation for AnotherCustomWidget.