Я пытаюсь выполнить аутентификацию с помощью Riverpod StateNotifier
и FutureProvider
, но сталкиваюсь с ошибкой при использовании метода when
, сталкивающегося с этой ошибкой.
Метод «когда» не может быть вызван безоговорочно, потому что получатель может быть «нулевым». Попробуйте сделать вызов условным (используя '?.') или добавив к цели нулевую проверку ('!').
даже при добавлении !
показывает это
Метод «когда» не определен для типа «Объект».⏎Попробуйте исправить имя на имя существующего метода или определить метод с именем «когда».
class MainPage extends ConsumerWidget {
const MainPage({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
final state = ref.watch(emailPasswordSignInControllerProvider);
return state.when(
data: (state) {
return state == AuthState.authenticated
? const SharedLayout()
: const LoginScreen();
},
error: (error, stackTrace) => const Scaffold(
body: Center(child: Text("Error")),
),
loading: () => const Scaffold(
body: Center(
child: CircularProgressIndicator(),
),
),
);
вот контроллер:
class EmailPasswordSignInController extends StateNotifier<AsyncValue<AuthState>> {
EmailPasswordSignInController({required this.authRepository})
: super(const AsyncValue.data(AuthState.notAuthenticated));
final AuthRepository authRepository;
Future<void> submit(String email, String password) async {
try {
state = const AsyncValue.loading();
await authRepository.signInWithEmailAndPassword(email, password);
state = const AsyncValue.data(AuthState.authenticated);
} catch (e, st) {
state = AsyncValue.error(e, st);
}
}
}
final emailPasswordSignInControllerProvider = StateNotifierProvider((ref) {
final authRepository = ref.watch(authRepositoryProvider);
return EmailPasswordSignInController(authRepository: authRepository);
});
И это мой репозиторий:
class AuthRepository {
Future<String> signInWithEmailAndPassword(
String email,
String password,
) async {
try {
final String token;
final Map<String, dynamic> jsonData;
final url = Uri.parse('http://192.168.1.9:5000/api/v1/auth/login');
final response = await http.post(url,
body: jsonEncode({
"email": email,
"password": password,
}),
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
});
jsonData = jsonDecode(response.body);
if (response.statusCode == 200) {
token = jsonData['token'];
return token;
}
return "error";
} on Exception catch (e) {
print(e.toString());
return e.toString();
}
}
}
final authRepositoryProvider = Provider<AuthRepository>((ref) {
return AuthRepository();
});
Ошибка говорит о том, что state
, где вы определяете его как final state = ref.watch(emailPasswordSignInControllerProvider);
, может возвращать нулевое значение. Таким образом, вы можете добавить туда оператор проверки null, если уверены, что он не вернет null
final state = ref.watch(emailPasswordSignInControllerProvider)!;
Или вместо этого вы можете вызвать его условно, чтобы, если состояние возвращает нулевое значение, оно не выполняло .when:
return state?.when
Вам также необходимо определить тип вашего провайдера следующим образом:
final emailPasswordSignInControllerProvider = StateNotifierProvider<EmailPasswordSignInController, AsyncValue<AuthState>>( (ref)
пожалуйста, прочитайте сообщение полностью, я показал ошибку, которая появляется при его добавлении.
Вероятно, это из-за оператора нулевой проверки (!). можно попробовать другое решение? если нет, попробуйте определить тип вашего провайдера следующим образом: final emailPasswordSignInControllerProvider = StateNotifierProvider<EmailPasswordSignInController, AsyncValue<AuthState>>( (ref)
с нулевой проверкой его, вероятно, определяют как <AsyncValue<AuthState>>? отсюда и ошибка
final state = ref.watch(emailPasswordSignInControllerProvider) ?? "";
попробуйте использовать это, это сработает, или используйте в этом
final state = ref.watch(emailPasswordSignInControllerProvider ?? "");
это исправило ошибку:
StateNotifierProvider<EmailPasswordSignInController, AsyncValue>((ref) {
final authRepository = ref.watch(authRepositoryProvider);
return EmailPasswordSignInController(authRepository: authRepository);
});
Если вы поняли это из моего комментария, я буду признателен за мое время :)
знаете ли вы, могу ли я обрабатывать ошибки, поступающие от моего контроллера, он все равно регистрирует меня, даже если есть error@Texv
Прекратите использовать StateNotifier и все остальное, что не было представлено в Riverpod 2. Стало бы более очевидным, что ваше состояние может быть обнуляемым, потому что метод сборки вашего подкласса Notifier должен быть обнуляемым.