Reputation: 9
I'm using riverpod with code generation for state management. Here, I've a variable named 'handle' which is passed onto the constructor of my widget and then I need to pass this variable in a list to a network call function.
Network call code
@riverpod
Future<List<User>?> getUsers(GetUsersRef ref, String handle) async {
....
}
Wen I make a network call using ref.watch(GetUsersProvider(handle)) in my consumerWidget, it works fine in this case but the problem arises when I want to pass a list of string to my network call function.
Network call code 2
@riverpod
Future<List<User>?> getUsers(GetUsersRef ref, List<String> handles) async {
....
print("Network call successful");
}
In this case when I call ref.watch(GetUsersProvider([handle]), my widget continuously rebuilds itself and never stops loading even though the network call is successful. How should I tackle this?
I tried passing const List<String> = ['handleName']
, this works but then I can't really create a const List of Strings using the handle variable passed to the constructor.
How do you guys pass a List of String to a provider in riverpod using code generation?
Upvotes: 1
Views: 396
Reputation: 470
Make a custom object eg- Params and as mentioned by @Randal Schwartz , use Equatable to ensure accurate object identity comparisons.
In your pubspec.yml
file add equatable
dependencies:
flutter:
sdk: flutter
equatable: ^2.0.5
Now make a custom class to pass as argument and extend it with Equatable
. You can include any properties you want to consider when determining equality by passing them in the props
list. In my case i just passed the whole list of string. But you can include additional properties in the class, such as another string, and include them in the props
list for equality comparison.
import 'package:equatable/equatable.dart';
class Params extends Equatable {
final List<String> strings;
Params(this.strings);
@override
List<Object?> get props => [strings];
}
When you pass arguments to Riverpod, it creates a provider for each argument. In your scenario, it generates a number of providers equal to the length of the list. .family
. Riverpod distinguishes each provider by comparing it against its arguments using ==
to ensure provider identity. Since you passed a list, it created multiple providers with the same type but different values. So use custom object with Equatable and it will work.
And it's advisable to use autodispose
when utilizing family
in providers.
Upvotes: 1
Reputation: 4844
From the documentation Passing parameters to a provider (family) :
When using code generation, we no-longer need to rely on the family modifier to pass parameters to a provider. Instead, the main function of our provider can accept any number of parameters, including named, optional, or default values.
Do note however that these parameters should have still have a consistent ==. Meaning either the values should be cached, or the parameters should override ==.
The last paragraph matters to us now. Off the top of my head, the idea comes to making an immutable wrapper for the list (use freezed), or using an immutable list type (third-party packages).
Upvotes: 0