Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

navigation inside Futurebuilder

I am trying to navigate after login inside futurebuilder. api request done successfully but navigation getting error while testing. Help me How to use futurebuilder properly.

child: ElevatedButton(
                onPressed: () {
                  // Validate returns true if the form is valid, or false otherwise.
                  if (_mobileKey.currentState!.validate()) {
                    FutureBuilder<Loginuser>(
                      future: loginuser(mobileController.text.toString(),
                          passwordController.text.toString()),
                      builder: (context, snapshot) {
                        if (snapshot.hasData) {
                          context.go('/Home');
                          return Text(snapshot.data!.message);
                        } else if (snapshot.hasError) {
                          return Text('${snapshot.error}');
                        }

                        // By default, show a loading spinner.
                        return const CircularProgressIndicator();
                      },
                    );
                  }

                  context.go('/Home');
                },
                child: const Text('Submit')),

I tried this its not working. I am using " go_router: ^5.2.4 " for navigation

like image 579
Hari .S Avatar asked Mar 12 '26 09:03

Hari .S


1 Answers

TLDR: Add:

 WidgetsBinding.instance.addPostFrameCallback((_) =>
                context.go('/Home'));

to the FutureBuilder


I managed to reproduce the problem with this example. Let's take a look.

If you run this code:

import 'package:flutter/material.dart';

void main() => runApp(MainApp());

class MainApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: Scaffold(body: Test()),
    );
  }
}

class Test extends StatelessWidget {
  const Test({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return FutureBuilder(
        future: printHello(),
        builder: (context, snapshot) {
          if (snapshot.hasData) {
            Navigator.push(
                context, MaterialPageRoute(builder: (context) => HomePage()));

            return Text(snapshot.data.toString());
          } else if (snapshot.hasError) {
            return Text("error");
          } else {
            return Center(child: CircularProgressIndicator());
          }
        });
  }
}

Future<String> printHello() async {
  return Future.value("Hello");
}

class HomePage extends StatelessWidget {
  const HomePage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(body: const Text("home page"));
  }
}

You'll see an error:

setState() or markNeedsBuild() called during build.

So, to fix the problem, you need to use WidgetsBinding.instance.addPostFrameCallback:

WidgetsBinding.instance.addPostFrameCallback((_) =>
                Navigator.push(context, MaterialPageRoute(builder: (context) {
                  return HomePage();
                })));

but for your example for go_router, add this line:

 WidgetsBinding.instance.addPostFrameCallback((_) =>
                context.go('/Home'));

Complete working example:

import 'package:flutter/material.dart';

void main() => runApp(MainApp());

class MainApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: Scaffold(body: Test()),
    );
  }
}

class Test extends StatelessWidget {
  const Test({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return FutureBuilder(
        future: printHello(),
        builder: (context, snapshot) {
          if (snapshot.hasData) {
            WidgetsBinding.instance.addPostFrameCallback((_) =>
                Navigator.push(context, MaterialPageRoute(builder: (context) {
                  return HomePage();
                })));

            return Text(snapshot.data.toString());
          } else if (snapshot.hasError) {
            return Text("error");
          } else {
            return Center(child: CircularProgressIndicator());
          }
        });
  }
}

Future<String> printHello() async {
  return Future.value("Hello");
}

class HomePage extends StatelessWidget {
  const HomePage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(body: const Text("home page"));
  }
}

See also

setState() or markNeedsBuild called during build

like image 162
MendelG Avatar answered Mar 14 '26 22:03

MendelG



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!