如何解决如何访问riverpod中statenotifier中的值和函数
我使用 Riverpod 中的 statenotifier
实现了用户身份验证,但我不知道它是如何以这种方式工作的。我必须创建两个提供程序,一个 StateNotifierProvider
用于读取值,一个 Provider
用于相同的 statenotifier
以访问 statenotifier
中的函数。
final signInStateNotifierProvider =
StateNotifierProvider((ref) => SignInStateNotifier(authentication));
final signInProvider =
Provider((ref) => ref.watch(signInStateNotifierProvider));
这是我的 statenotifier 类
class SignInStateNotifier extends StateNotifier<AuthFormStates> {
SignInStateNotifier(this._authFacade) : super(AuthFormStates.initial());
final SignInAuthFacade _authFacade;
Future mapEventToState(SignInFormEvents event) async {
event.map(
// email changed
emailChanged: (event) {
state = state.copyWith(
emailAddress: EmailAddress(event.email),authFailureOrSuccess: none(),);
},// password changed
passwordChanged: (event) {
state = state.copyWith(
password: Password(event.password),signInWithEmailAndPasswordpressed: (event) async {
await _performActionWithEmailAndPassword(
_authFacade.signInWithEmailAndPassword,);
}
Future _performActionWithEmailAndPassword(
Future<Either<AuthFailure,Unit>> Function({
@required EmailAddress emailAddress,@required Password password,})
action,) async {
Either<AuthFailure,Unit> result;
final isEmailValid = state.emailAddress.isValid();
final isPasswordValid = state.password.isValid();
if (isEmailValid && isPasswordValid) {
state = state.copyWith(
isSubmitting: true,);
result = await action(
emailAddress: state.emailAddress,password: state.password,);
state = state.copyWith(
authFailureOrSuccess: some(result),);
}
state = state.copyWith(
isSubmitting: false,showErrorMessage: true,authFailureOrSuccess: optionOf(result),);
}
}
这就是我访问 statenotifier 的方式
class HomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
body: ProviderListener<AuthFormStates>(
provider: signInStateNotifierProvider.state,onChange: (context,state) {
state.authFailureOrSuccess.fold(
() {},(either) => either.fold(
(failure) {
return null;
},(success) => null,),);
},child: Consumer(
builder: (context,watch,child) {
final providerState = watch(signInProvider);
final stateNotifierState =
watch(signInStateNotifierProvider.state);
return Form(
autovalidateMode: AutovalidateMode.onUserInteraction,child: Column(
children: [
TextFormField(
onChanged: (value) => providerState.mapEventToState(
SignInFormEvents.emailChanged(value)),validator: (_) => stateNotifierState
.emailAddress.validatedobject
.fold(
(l) => l.maybeMap(
orElse: () => null,invalidEmail: (_) => 'Invalid Email'),(_) => null),TextFormField(
onChanged: (value) => providerState.mapEventToState(
SignInFormEvents.passwordChanged(value)),validator: (_) =>
stateNotifierState.password.validatedobject.fold(
(l) => l.maybeMap(
orElse: () => null,invalidPassword: (_) => 'Invalid Password'),TextButton(
onpressed: () {
providerState.mapEventToState(const SignInFormEvents
.signInWithEmailAndPasswordpressed());
},child: const Text('Hello World'))
],));
},);
}
}
这很好用,但我需要知道这是正确的方法还是我错了。有没有其他方法可以实现我正在做的事情?请给出解决方案。
而且我所做的也是正确的,请告诉我它是如何以这种方式工作的。我需要清楚地了解它的工作原理。
提前致谢:)
解决方法
我认为 signInProvider
是多余的。它没有什么特别的,只是听signInStateNotifierProvider
。
在小部件 HomePage 中,您实际上可以使用 context.read(provider)
调用提供程序内部的函数而无需查看状态,因此您可以更改:
final providerState = watch(signInProvider);
providerState.mapEventToState(...)
到
final providerState = context.read(signInStateNotifierProvider);
providerState.mapEventToState(...)
或
context.read(signInStateNotifierProvider).mapEventToState(...)
另外,如果你追求最好的表现,你在验证价值时不需要听(看)signInStateNotifierProvider
。 (因为你没有在widget树中重建任何东西,只是获取数据)
validator: (_) => context.read(signInStateNotifierProvider).emailAddress.validatedObject...
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。