【发布时间】:2021-08-18 12:54:10
【问题描述】:
我们正在使用 GraphQL 将我们的后端与我们的移动应用程序连接起来。我们使用 Riverpod 来处理全局状态、依赖注入等。
我们正在使用提供程序来处理 GraphQL 客户端,一开始没有任何身份验证标头,而用户未进行身份验证(这将处理未经身份验证的请求,如登录或注册),在用户通过身份验证后,提供令牌的令牌提供程序已更新,它必须更新作为应用程序每个存储库用户的客户端提供程序:
final StateProvider<String> tokenProvider =
StateProvider<String>((_) => '', name: "Token Provider");
final graphQLClientProvider = Provider<GraphQLClient>(
(ref) {
final String token = ref.watch(tokenProvider).state;
final Link _link = HttpLink(
'http://192.168.1.36:1337/graphql',
defaultHeaders: {
if (token != '') 'Authorization': 'Bearer $token',
});
return GraphQLClient(
cache: GraphQLCache(),
link: _link,
);
},
name: "GraphQL Client Provider",
);
这里有太多问题:
- 更新令牌后,客户端发生了变化,由此导致更新令牌的函数无法正常完成:
[ +141 ms] E/flutter ( 8361): [ERROR:flutter/lib/ui/ui_dart_state.cc(199)] Unhandled Exception: Bad state: Tried to use AuthNotifier after `dispose` was called.
[ ] E/flutter ( 8361):
[ ] E/flutter ( 8361): Consider checking `mounted`.
[ ] E/flutter ( 8361):
[ ] E/flutter ( 8361): #0 StateNotifier._debugIsMounted.<anonymous closure> (package:state_notifier/state_notifier.dart:128:9)
[ ] E/flutter ( 8361): #1 StateNotifier._debugIsMounted (package:state_notifier/state_notifier.dart:135:6)
[ ] E/flutter ( 8361): #2 StateNotifier.state= (package:state_notifier/state_notifier.dart:155:12)
[ ] E/flutter ( 8361): #3 AuthNotifier.signIn (package:thesis_cancer/features/auth/application/auth.notifier.dart:84:7)
[ ] E/flutter ( 8361): <asynchronous suspension>
[ ] E/flutter ( 8361): #4 _LoginCardState._submit (package:flutter_login/src/widgets/auth_card.dart:503:15)
[ ] E/flutter ( 8361): <asynchronous suspension>
[ ] E/flutter ( 8361):
这意味着当令牌更新时,接收存储库的身份验证通知器取决于提供的客户端被更新/更改(遵循链):
final authRepositoryProvider = Provider<AuthRepository>(
(ref) => GraphQLAuthRepository(client: ref.read(graphQLClientProvider)),
name: 'Auth Repository Provider',
);
final authNotifierProvider = StateNotifierProvider<AuthNotifier, AuthState>(
(ref) => AuthNotifier(
authRepository: ref.watch(authRepositoryProvider),
dataStore: ref.watch(dataStoreRepositoryProvider),
profileRepository: ref.watch(profileRepositoryProvider),
tokenController: ref.watch(tokenProvider.notifier),
userController: ref.watch(userEntityProvider.notifier),
),
name: "Authentication Notifier Provider",
);
条件中断的通知函数(if):
Future<String?> signIn({
required String username,
required String password,
}) async {
try {
final Map<String, dynamic> rawUser = await authRepository.signIn(
identifier: username, password: password) as Map<String, dynamic>;
final User sessionUser = User.fromJson(rawUser);
if (sessionUser.confirmed != false) {
tokenController.state = sessionUser.token!; <-- Bug begins here
}
await dataStore.writeUserProfile(sessionUser);
userController.state = sessionUser;
state = const AuthState.loggedIn();
} on LogInFailureByBadRequest {
return "E-posta veya şifre geçersiz.";
} on LogInFailure catch (error) {
return error.toString();
}
}
在the issue we opened 上的cmets 之后,我们将ProviderReference 添加到我们的通知程序(在this question 之后),但它不起作用:
AuthNotifier(
this._ref, {
required this.authRepository,
required this.profileRepository,
required this.dataStore,
required this.tokenController,
required this.userController,
}) : super(const AuthState.loading());
final ProviderReference _ref;
final ProfileRepository profileRepository;
final AuthRepository authRepository;
final DataStoreRepository dataStore;
final StateController<User?> userController;
final StateController<String> tokenController;
此时,我们不明白这里有什么问题。
更新
我们在 StateNotifier 及其提供者中删除了此更改。
使用 Riverpod 处理授权令牌和 GraphQL 客户端的正确方法是什么?
谢谢。
【问题讨论】:
-
您使用的是什么版本的 Riverpod?
-
我还在用
hooks_riverpod: ^0.14.0+4。 -
添加使用 authNotifier 的片段
标签: flutter dart graphql riverpod