Search code examples
androidflutterriverpodriverpod-generator

The method 'registerUser' isn't defined for the type 'AsyncValue'


This is my app_router.dart. I am setting the redirection logic but there is this error of AsyncValue. The redirection logic is - The methods in my repo - register user and register business- if true or false based on that it will go to the respective page also i want to add the shared preference for persistence.

import 'package:fundsaudit/src/features/Myshop/presentation/myproducts_screen.dart';
import 'package:fundsaudit/src/features/auth/data/firebaseauth_repository.dart';
import 'package:fundsaudit/src/features/auth/presentation/sign_in_screen.dart';
import 'package:fundsaudit/src/features/home/presentation/home_screen.dart';
import 'package:fundsaudit/src/features/registration/data/registration_repository.dart';
import 'package:fundsaudit/src/features/registration/presentation/account_setup_screen.dart';
import 'package:fundsaudit/src/features/registration/presentation/business_setup_screen.dart';
import 'package:fundsaudit/src/routing/go_refresh_stream.dart';
import 'package:go_router/go_router.dart';
import 'package:fundsaudit/bottomNav.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
import 'package:fundsaudit/src/features/Myshop/presentation/myproducts_screen.dart';
import 'package:shared_preferences/shared_preferences.dart';
part "app_router.g.dart";

enum AppRoute {
  signIn,
  registration,
  personalSetup,
  businessSetup,
  home,
  phoneNo,
  otp,
}

@riverpod
GoRouter goRouter(GoRouterRef ref) {
  final authRepository = ref.watch(firebaseAuthRepositoryProvider);
  final registrationRepo = ref.watch(registrationRepoProvider);

  return GoRouter(
    initialLocation: "/signIn",
    debugLogDiagnostics: true,
    refreshListenable: GoRouterRefreshStream(authRepository.authStateChanges()),
    redirect: (context, state) async {
      final currentUser = authRepository.currentUser;
      if (currentUser == null) {
        return '/signIn';
      }

      final isUserRegistered = await registrationRepo.registerUser(currentUser.uid);
      final isBusinessRegistered = await registrationRepo.registerBusiness(currentUser.uid);

      if (!isUserRegistered) {
        return '/setup/personal';
      } else if (!isBusinessRegistered) {
        return '/setup/business';
      } else {
        return '/home';
      }
    },
    routes: [
      GoRoute(
        path: '/home',
        name: AppRoute.home.name,
        pageBuilder: (context, state) => const NoTransitionPage(child: HomeScreen()),
      ),
      GoRoute(
        path: '/signIn',
        name: AppRoute.signIn.name,
        pageBuilder: (context, state) => const NoTransitionPage(child: PhoneNumber()),
        routes: [
          GoRoute(
            path: 'otp/:phoneNo',
            name: AppRoute.otp.name,
            pageBuilder: (context, state) {
              final phoneNo = state.pathParameters['phoneNo']!;
              return NoTransitionPage(child: OTPPage(phoneNumber: phoneNo));
            },
          ),
        ],
      ),
      GoRoute(
        path: '/setup/personal',
        name: AppRoute.personalSetup.name,
        pageBuilder: (context, state) => NoTransitionPage(child: AccountSetupScreen()),
      ),
      GoRoute(
        path: '/setup/business',
        name: AppRoute.businessSetup.name,
        pageBuilder: (context, state) => const NoTransitionPage(child: BusinessSetupScreen()),
      ),
    ],
  );
}
class RegistrationRepo {
  RegistrationRepo(
    this._api,
  );
  final Api? _api;

Future<bool> registerUser(data) async {
    if (_api == null) {
      debugPrint("API instance not available");
      return false; // API not available, registration cannot proceed
    }
    try {
      await _api.post('/auth/registerUser', data);
      debugPrint("User registration successful, $data");
      return true; // Registration successful
    } catch (e) {
      debugPrint("Error registering user, $e");
      return false; // Registration failed
    }
  }

Future<bool> registerBusiness(data) async {
    if (_api == null) {
      debugPrint("API instance not available");
      return false;
    }
    try {
      await _api.post('/auth/registerBusiness', data);
      debugPrint("Business registration successful, $data");
      return true;
    } catch (e) {
      debugPrint("Error registering business, $e");
      return false;
    }
  }

@riverpod
Future<RegistrationRepo> registrationRepo(RegistrationRepoRef ref) async {
  var api = await ref.watch(apiProvider.future);
  return RegistrationRepo(api);
    }

Solution

  • registrationRepo returns a future, which makes reading the provider gives you an AsyncValue.

    Since registrationRepo is only used inside a callback in goRouter provider, and not directly in the provider body, you can instead use ref.read directly inside the redirect callback, and read the future property of the provider:

    @riverpod
    GoRouter goRouter(GoRouterRef ref) {
      // ...
    
      return GoRouter(
        // ...
        redirect: (context, state) async {
          // ...
    
          // This will give you a `RegistrationRepo`
          final registrationRepo = await ref.read(registrationRepoProvider.future);
    
          final isUserRegistered = await registrationRepo.registerUser(currentUser.uid);