Comments (20)
@rrousselGit but i still confused , i should make 2 variable to define state what i want listen and method from StateNotifier ?
something like :
final IsLoading isLoading = useProvider(isLoadingProvider); // it for method toggleLoading();
final bool loading = useProvider(isLoadingProvider.state); // it for listen state
Because documentation example i attach above , not showing to listen state and only show call method counter.increment()
from riverpod.
As said by StateNotifierProvider, if you want to listen to the state of a StateNotifier, use "useProvider(myStateNotifierProvider.state)"
from riverpod.
Oh my bad, that's for the next changes
For now you can do ref.read(userProvider).addListener((state) {...}
from riverpod.
Not necessarily a good practice, as the value may change over time.
You may want a StreamProvider for that reason too
from riverpod.
How would I listen to state changes without using a hookwidget? Is the below correct?
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("Search Sellers")),
body: Consumer(
builder: (context, watch, child) {
var location = watch(mapApiProvider.state); // mapApiProvider is a StateNotifierProvider
var myLatLong = {
location.userLocation.latitude,
location.userLocation.longitude
};
return Center(
child: Text("You're location is ${myLatLong.toString()}"));
},
),
);
}
from riverpod.
Yes this is correct
from riverpod.
Yes, that is correct.
Although the counter example does counter.read(context).increment()
from riverpod.
It's more clear for me. But it's have option/possible make it more simple ? something like i only make 1 variable final loading = useProvider(loadingProvider)
. and this variable can use for calling method and listen state ?
final loading = userProvider(loadingProvider);
//Listen state
Text(loading.state);
//Calling method
loading.toggleLoading(value);
with above approach , will make warning like my thread . Because make 2 variable with almost same name , make me confused.
from riverpod.
No this is expected
It allows reading the notifier without listening to the state, to avoid pointless rebuilds.
from riverpod.
Mhm, I am trying to do exactly that (one for reading and one for methods), but I can't seem to get the method way to work?
final StateNotifierProvider themeProvider = StateNotifierProvider((ref) {
return ThemeManager();
});
class ThemeManager extends StateNotifier<ThemeData> {
ThemeManager() : super(darkTheme);
void setTheme(ThemeData theme) async {
state = theme;
}
}
Then now when I try to obtain toggle setTheme
, I retrieve it like so:
final ThemeManager themeManager = useProvider(themeProvider);
But I get error of:
The argument type 'StateNotifierProvider<StateNotifier>' can't be assigned to the parameter type 'ProviderListenable'.
What am I doing wrong here?
EDIT: Nevermind, looks like I just had to remove the type annotation for:
- final StateNotifierProvider themeProvider = StateNotifierProvider((ref) { + final themeProvider = StateNotifierProvider((ref) { return ThemeManager(); });
from riverpod.
As I mentioned, the syntax is "useProvider(themeProvider.state)"
from riverpod.
@rrousselGit i don't know it's should create new issue or not , i got this warning again but in FutureProvider i want know this is best practice or not.
I have simple Http get request to show all user from server, and i using manage it using FutureProvider
Api
class UserGoogleApi {
Future<List<UserGoogleModel>> getAllUser() async {
final result = await reusableRequestServer.requestServer(() async {
final response =
await http.get('${appConfig.baseApiUrl}/${appConfig.userGoogleController}/getAllUser');
final Map<String, dynamic> responseJson = json.decode(response.body);
if (responseJson['status'] == 'ok') {
final List list = responseJson['data'];
final listUser = list.map((e) => UserGoogleModel.fromJson(e)).toList();
return listUser;
} else {
throw responseJson['message'];
}
});
return result;
}
}
User Provider
class UserProvider extends StateNotifier<UserGoogleModel> {
UserProvider([UserGoogleModel state]) : super(UserGoogleModel());
Future<UserGoogleModel> searchUserByIdOrEmail({
String idUser,
String emailuser,
String idOrEmail = 'email_user',
}) async {
final result = await _userGoogleApi.getUserByIdOrEmail(
idUser: idUser,
emailUser: emailuser,
idOrEmail: idOrEmail,
);
UserGoogleModel temp;
for (var item in result) {
temp = item;
}
state = UserGoogleModel(
idUser: temp.idUser,
createdDate: temp.createdDate,
emailUser: temp.emailUser,
imageUser: temp.emailUser,
nameUser: temp.nameUser,
tokenFcm: temp.tokenFcm,
listUser: state.listUser,
);
return temp;
}
Future<List<UserGoogleModel>> showAllUser() async {
final result = await _userGoogleApi.getAllUser();
state.listUser = result;
return result;
}
}
final userProvider = StateNotifierProvider((ref) => UserProvider());
final showAllUser = FutureProvider.autoDispose((ref) async {
final usrProvider = ref.read(userProvider);
final result = await usrProvider.showAllUser();
return result;
});
After that setup, i simply can call showAllUser like this :
Consumer((ctx, read) {
final provider = read(showAllUser);
return provider.when(
data: (value) {
return ListView.builder(
itemCount: value.length,
shrinkWrap: true,
itemBuilder: (BuildContext context, int index) {
final result = value[index];
return Text(result.nameUser);
},
);
},
loading: () => const CircularProgressIndicator(),
error: (error, stackTrace) => Text('Error $error'),
);
}),
it's no problem if http request don't have required parameter, but i got problem if my http request required parameter. I don't know how to handle this.
Let's say , i have another http get to show specific user from id user or email user. Then API look like :
User Provider
final showSpecificUser = FutureProvider.autoDispose((ref) async {
final usrProvider = ref.read(userProvider);
final result = await usrProvider.searchUserByIdOrEmail(
idOrEmail: 'id_user',
idUser: usrProvider.state.idUser, // => warning on "state"
);
return result;
});
When i access idUser from userProvider using usrProvider.state.idUser
, i got this warning again The member 'state' can only be used within instance members of subclasses of 'package:state_notifier/state_notifier.dart'.
How can i get idUser from userProvider ? and i want know this is best practice using FutureProvider ?
from riverpod.
from riverpod.
@rrousselGit ref.read(userProvider.state);
give me error :
The argument type 'StateNotifierStateProvider<UserGoogleModel>' can't be assigned to the parameter type 'ProviderBase<ProviderDependency<dynamic>, Object>'.
I think method read on Consumer and FutureProvider it's different.
read on Consumer accept Res Function<Res>(ProviderBase<ProviderDependencyBase, Res>)
read on FutureProviduer accept ProviderBase<ProviderDependency<T>, Object>
from riverpod.
@rrousselGit i have 2 problem with this approach .
- Value obtained from listener always null , although i'm sure it's have value.
UserProvider
final showSpecificUser = FutureProvider.autoDispose((ref) async {
UserGoogleModel temp;
final usrProvider = ref.read(userProvider);
usrProvider.addListener((state) async {
final result = await usrProvider.searchUserByIdOrEmail(emailuser: state.emailUser);
// print('listenern RESULT ${result.nameUser} || ${result.emailUser} || ${result.idUser}');
temp = result;
print('Temp RESULT ${result.nameUser} || ${result.emailUser} || ${result.idUser}');
});
return temp;
});
And i simple call it like this
Consumer((ctx, read) {
final provider = read(showSpecificUser);
return provider.when(
data: (value) {
if (value == null) {
return Text('Not have data');
}
// print('specific user ${value.nameUser}');
return Text(value.nameUser ?? 'null');
},
loading: () => const CircularProgressIndicator(),
error: (error, stackTrace) => Text(error.toString()),
);
}),
Temp Result
2.With addListener((state)async{})
it will always listen ,although i already used FutureProvider.autoDisposed.
Although already used FutureProvider.autoDisposed , after logout it's still listen old value. please see below gif.
from riverpod.
Can't you just add a getter for state in your class that extends StateNotifier? Assuming that your FutureProvider is being properly disposed after each use that should be a suitable workaround until the new changes to Riverpod are live. I did a quick test to see and it does work. Make sure you define a getter like this and don't override the default defined by StateNotifier.
class A extends StateNotifier<B> {
...
static final provider = StateNotifierProvider((ref) => A());
getState() => state;
...
}
final provider = FutureProvider.autoDispose((ref) async {
final a = ref.read(A.provider);
final t = a.getState();
print(t);
});
Not ideal but seems like a fine workaround. I believe the intention of state being inaccessible outside is to ensure state manipulations are handled by the StateNotifier itself, so using a getter in the meantime wouldn't be the end of the world.
from riverpod.
@AlexHartford interesting, i will try it .
from riverpod.
@rrousselGit based on my above code , what's the problem with my code ?
from riverpod.
If "t" changes,this will not print the new value
from riverpod.
@rrousselGit I think best option it's waiting you implement what you mention on it
from riverpod.
Related Issues (20)
- `yarn dev -l {LANG}` is needed when hosting documentation website locally for specific locale with docusaurus
- Stream from StreamProvider is not unsubscribed to when widgets get disposed
- There is no way to handle the "done" event on the stream of a StreamProvider
- `ref.invalidate(familyProvider)` is not working with scoped providers
- PageController stateprovider doesn't work when .previousPage() or nextPage() is pressed HOT 1
- beforeDispose or beforeInvalidate hook, happen before invalidate HOT 6
- Multiple invalidation of Providers HOT 2
- Unable to use the latest riverpod in flutter version lower than 3.16 HOT 2
- The getter 'variable2' isn't defined for the class 'PropertyAccessorElement'. HOT 10
- Can't copy code snippet from main landing page in website HOT 2
- Infinitely call child's `useEffect` when parent and child both `extends HookConsumerWidget` HOT 2
- riverpod_lint didn't show assists (in context menu) HOT 10
- Would separating asyncValue into its own package be useful? HOT 1
- Overriden providers are not passed to dialogs or modals HOT 5
- Unexpected dispose behavior in AutoDisposeProvider with nested watch methods HOT 3
- `Provider1` will never get disposed if `Provider2` gets disposed before it listens to or watches `Provider1` HOT 1
- Provider delegates onCancel and onDispose aren't invoked after invalidation when there are no remaining listeners HOT 3
- state works weird HOT 1
- Provider gets disposed before future completes when using `ref.read(provider.future)` HOT 4
- Pagination approach at pub example won't dispose fetchPackagesProvider of a page even if it's out of screen
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from riverpod.