rrousselGit / riverpod

A reactive caching and data-binding framework. Riverpod makes working with asynchronous code a breeze.
https://riverpod.dev
MIT License
6.17k stars 943 forks source link

What is the best way to create differentiated providers of the same structure by instances of the same widget class? #713

Closed TykanN closed 3 years ago

TykanN commented 3 years ago

Describe what scenario you think is uncovered by the existing examples/articles Hello. I want to produce differentiated providers of the same structure by instances of the same widget class. I implemented it using .family and .autoDispose modifier.

For example,

final selectorControllerProvider = ChangeNotifierProvider.autoDispose.family<SelectorController, string>((ref, id) => SelectorController(id));

class SelectorController extends ChangeNotifier {
  final String tag;
  SelectorController(this.tag);

  int index = 0;

  void setIndex(int value) {
    index = value;
    notifyListeners();
  }
  // ... many other variables, methods
}

class Selector extends ConsumerWidget{
  final String tag;
  const Selector(this.tag);

  @override
  Widget build(context, watch){
    var index = watch(selectorControllerProvider(tag)).index;
    return ...
  }
}

It is possible that there are many Selector Widgets. But a Selector use its own provider because state management(in this case, index) should be separated from another Selector instance.

I wonder that using .family is correct way. I think it's not safe because another widget can access provider declared as global constant.(ex. When tag parameter is duplicated by human error, multiple widgets share one provider.)

If not, should i create other ProviderScope in Selector widget class?

Users can add Selector widget as many as they wants. so it's impossible to declare provider separately. One provider and one widget are a pair.

Describe why existing examples/articles do not cover this case There is only provider declared as global constant. I can't find example of widget-provider binding.

Additional context in this case, is stful widget better?

rrousselGit commented 3 years ago

It looks like you are trying to use Providers for something that they aren't meant to be used for.
Providers are for state shared between multiple widgets. Whereas you want a state unique to the widget.

Maybe you want to use a StatefulWidget instead. flutter_hooks, a cousin of Riverpod, is another solution.

You could do:

class Selector extends HookWidget {
  @override
  Widget build(context) {
    final index = useState(0);
  }
}
TykanN commented 3 years ago

@rrousselGit

Providers are for state shared between multiple widgets.

😃 I understand what you meant. I tried to make the easy one difficult.

I'll consider using the hooks. it looks like a simplification of StatefulWidget.