skip to Main Content

i am confused where can i implement the init state condition for future builder. see whats wrong in my code. in flutter documentation is refer initState for Future builder widget.

` @override
  void initState() {
    super.initState();
    futureLoginuser = loginuser();
  }`

i am trying to navigate new screen after response data arrives.my complete code is here i am using go_router for navigation.

class LoginForm extends StatefulWidget {
  const LoginForm({Key? key}) : super(key: key);

  @override
  LoginFormState createState() {
    return LoginFormState();
  }
}

class LoginFormState extends State<LoginForm> {

  TextEditingController mobileController = TextEditingController();
  TextEditingController passwordController = TextEditingController();
  final _mobileKey = GlobalKey<FormState>();
  final _passwordKey = GlobalKey<FormState>();

  get message => null;

  get messagecode => null;

  get userinfo => null;

  get token => null;

  Future<Loginuser> loginuser(String mobile, String password) async {
    final response = await http.post(
        Uri.parse('https:random.url/api/login'),
        body: {'mobile': mobile, 'password': password});

    if (response.statusCode == 200) {
      return Loginuser.fromJson(jsonDecode(response.body));
      }
    } else {
      throw Exception('Failed to update');
    }
  @override
  Widget build(BuildContext context) {
    return Form(
        key: _mobileKey,
        child: Column(crossAxisAlignment: CrossAxisAlignment.center, children: [
          TextFormField(
            controller: mobileController,
            autofocus: true,
            keyboardType: TextInputType.phone,
            decoration: const InputDecoration(
              border: InputBorder.none,
              hintText: "Enter Your Mobile Number",
            ),
          ),
          TextFormField(
            controller: passwordController,
            key: _passwordKey,
            keyboardType: TextInputType.visiblePassword,
            decoration: const InputDecoration(
              border: InputBorder.none,
              hintText: "Enter Your Password",
            ),
          ),
          Padding(
            padding: const EdgeInsets.symmetric(vertical: 16.0),
            child: ElevatedButton(
                onPressed: () {
                    FutureBuilder<Loginuser>(
                      future: loginuser(mobileController.text.toString(),
                          passwordController.text.toString()),
                      builder: (context, snapshot) {
                        if (snapshot.hasData) {
                          print('snapshsot.hasdata');
                          context.go('/Home');
                        } else if (snapshot.hasError) {
                          return Text('${snapshot.error}');
                        }
                        return const CircularProgressIndicator();
                      },
                    );
                  }
                child: const Text('Submit')),
          ),
        ]));
  }
}

`

3

Answers


  1. Try this

    LoginUser? loginUser
     @override
      void initState() async{
        super.initState();
        futureLoginuser = await loginuser();
        ... // 👈 Your navigation here
      }`
    

    Try to make your build responsive by checking for loginUser

      @override
      Widget build(BuildContext context) {
        futureLoginuser == null ?
                      CircularProgressIndicator() : <Rest of your widget>
       }
    
    Login or Signup to reply.
  2. You are using the FutureBuilder wrong it is a Widget that builds itself based on the latest snapshot of interaction with a Future. Its usually used to build widgets that need input when a certain future is completed.

    In your case use this:

    //first make the onPressed function async
        child ElevatedButton(
            child: Container(),
            onPressed: () async {
              // then await the future You want to complete and then use `.then()` 
              //method to implement the code that you want to implement when the future is completed
              await loginuser(mobileController.text.toString(),
                      passwordController.text.toString())
                  .then((result) {
                print('future completed');
                context.go('/Home');
                // For errors use onError to show or check the errors.
              }).onError((error, stackTrace) {
                print(error);
              });
            });
    

    And do validate the form for any error with form key validation method.

    the only way to wait for the future to complete and do something is to use the Asynchronous function either directly as I have shown above or by using the try/catch method both will work fine.

    Login or Signup to reply.
  3. The way you are trying to implement is not correct, here is very basic example to do

    class LoginForm extends StatefulWidget {
      const LoginForm({Key? key}) : super(key: key);
    
      @override
      LoginFormState createState() {
        return LoginFormState();
      }
    }
    
    class LoginFormState extends State<LoginForm> {
      TextEditingController mobileController = TextEditingController();
      TextEditingController passwordController = TextEditingController();
      final _formKey = GlobalKey<FormState>();
    
      // your other variables
    
      bool isValidating = false;
    
      @override
      Widget build(BuildContext context) {
        return Form(
            key: _formKey,
            child: Column(crossAxisAlignment: CrossAxisAlignment.center, children: [
              TextFormField(
                controller: mobileController,
                autofocus: true,
                keyboardType: TextInputType.phone,
                decoration: const InputDecoration(
                  border: InputBorder.none,
                  hintText: "Enter Your Mobile Number",
                ),
              ),
              TextFormField(
                controller: passwordController,
                keyboardType: TextInputType.visiblePassword,
                decoration: const InputDecoration(
                  border: InputBorder.none,
                  hintText: "Enter Your Password",
                ),
              ),
              Padding(
                padding: const EdgeInsets.symmetric(vertical: 16.0),
                child: isValidating
                    ? const CircularProgressIndicator()
                    : ElevatedButton(
                        onPressed: () async {
                          if (_formKey.currentState!.validate()) {
                            setState(() {
                              isValidating = !isValidating;
                            });
                            final r = await loginuser(
                                mobileController.text.toString(),
                                passwordController.text.toString());
                            if (r != null) {
                              // save user state locally, using hive or what alternative you want
                              context.go('/Home');
                            } else {
                              ScaffoldMessenger.of(context)
                                  .showSnackBar(const SnackBar(
                                content: Text('Failed'),
                              ));
                            }
                            setState(() {
                              isValidating = !isValidating;
                            });
                          }
                        },
                        child: const Text('Submit')),
              ),
            ]));
      }
    
      Future<Loginuser?> loginuser(String mobile, String password) async {
        final response = await http.post(Uri.parse('https:random.url/api/login'),
            body: {'mobile': mobile, 'password': password});
    
        if (response.statusCode == 200) {
          return Loginuser.fromJson(jsonDecode(response.body));
        }
        return null;
      }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search