Search code examples
flutterdartflutter-providerflutter-navigation

How to navigate to another page after using a provider function in flutter?


I have created a function in my Login provider to verify OTP for my app like below.

Future<bool> verifyOtp(String otp) async {
    final _loginData = await SharedPreferences.getInstance();

    _isLoading = true;
    notifyListeners();
    _status = await AuthApi.verifyOtp(otp);
    _isLoading = false;
    _name = _loginData.getString('name');
    notifyListeners();
    return _status;
  }

Now whenever I am trying to use this on my code like below,

final bool status = await Provider.of<LoginProvider>(context, listen: false).verifyOtp(verificationCode);

// ignore: avoid_print
print("STATUS ==== " + status.toString());
if (status) {
  Navigator.of(context).pushReplacementNamed('/discover');
} else {
  ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text("Incorrect OTP!!!")));
}

It's giving me an exception like below -

Exception has occurred.
FlutterError (This widget has been unmounted, so the State no longer has a context (and should be considered defunct).
Consider canceling any active work during "dispose" or using the "mounted" getter to determine if the State is still active.)

Anyone please guide me, what is the actual way to navigate from a provider. I am very new in Provider. Thank you so much :)

----- Full Provider Code is Below -----

class LoginProvider with ChangeNotifier {
  bool _status = false;
  bool _isLoading = false;
  bool _isOtpScreen = false;
  String? _name;

  bool get isLoading => _isLoading;
  bool get isOtpScreen => _isOtpScreen;
  String? get name => _name;

  void sendOtp(String phone) async {
    _isLoading = true;
    notifyListeners();
    _status = await AuthApi.sendOtp(phone);
    _isLoading = false;
    _isOtpScreen = true;
    notifyListeners();
  }

  Future<bool> verifyOtp(String otp) async {
    final _loginData = await SharedPreferences.getInstance();

    _isLoading = true;
    notifyListeners();
    _status = await AuthApi.verifyOtp(otp);
    _isLoading = false;
    _name = _loginData.getString('name');
    notifyListeners();
    return _status;
  }
}


Solution

  • Use a GlobalKey you can access from anywhere to navigate

    Create the key

    final GlobalKey<NavigatorState> navigatorKey = new GlobalKey<NavigatorState>();
    void main() async {
     WidgetsFlutterBinding.ensureInitialized();
       runApp(MyApp());
    }
    

    Pass it to your App:

    new MaterialApp(
      title: 'MyApp',
      onGenerateRoute: generateRoute,
      navigatorKey: navigatorKey,
    );
    

    Use in your route:

        print("STATUS ==== " + status.toString());
        if (status) {
           Navigator.of(navigatorKey.currentContext).pushReplacementNamed('/discover');
        } else {
          ScaffoldMessenger.of(navigatorKey.currentContext).showSnackBar(const SnackBar(content:
          Text("Incorrect OTP!!!")));
        }