The following _TypeError was thrown building Builder(dirty, dependencies: [MediaQuery]): type 'Future<Null>' is not a subtype of type 'Widget'

0

Context:

I am building a simple login app with azure ad, the app logins just fine and gets the token and redirects to the next page just fine, but before it redirects it throws an error

Error:

The following _TypeError was thrown building Builder(dirty, dependencies: [MediaQuery]): type 'Future' is not a subtype of type 'Widget'

The relevant error-causing widget was: Builder file:///D:/Projects/flutter/aims_mobile/lib/screens/authentication/signin.dart:101:17 When the exception was thrown, this was the stack: #0 _SignInState.build. (package:aims_mobile/screens/authentication/signin.dart:133:25) #1 Builder.build (package:flutter/src/widgets/basic.dart:7185:48) #2 StatelessElement.build (package:flutter/src/widgets/framework.dart:4749:28) #3 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4675:15) #4 Element.rebuild (package:flutter/src/widgets/framework.dart:4369:5)

Code

class _SignInState extends State<SignIn> {
  static const String SCOPE ='';
  static const String TENANT_ID = 'organizations';
  static String authority = "";

  MsalMobile msal;
  bool isSignedIn = false;

  @override
  void initState() {
    super.initState();
    MsalMobile.create('assets/auth_config.json', authority).then((client) {
      setState(() {
        msal = client;
      });
      refreshSignedInStatus();
    });
  }

  /// Updates the signed in state
  refreshSignedInStatus() {
    msal.getSignedIn().then((loggedIn) {
      print('refreshing');
      setState(() {
        isSignedIn = loggedIn;
      });
    });
  }

  /// Signs a user in
  handleSignIn() async {
    await msal.signIn(null, [SCOPE]).then((result) {
      refreshSignedInStatus();
    }).catchError((exception) {
      if (exception is MsalMobileException) {
        logMsalMobileError(exception);
      } else {
        final ex = exception as Exception;
        print('exception occurred');
        print(ex.toString());
      }
    });
  }

  logMsalMobileError(MsalMobileException exception) {
    print('${exception.errorCode}: ${exception.message}');
    if (exception.innerException != null) {
      print(
          'inner exception = ${exception.innerException.errorCode}: ${exception.innerException.message}');
    }
  }

  /// Signs a user out.
  handleSignOut() async {
    try {
      print('signing out');
      await msal.signOut();
      print('signout done');
      refreshSignedInStatus();
    } on MsalMobileException catch (exception) {
      logMsalMobileError(exception);
    }
  }

  /// Gets the current and prior accounts.
  handleGetAccount() async {
    await msal.getAccount().then((result) {
      if (result.currentAccount != null) {
        print('current account id: ${result.currentAccount.id}');
        print('current account id: ${result.currentAccount.username}');
      } else {
        print('no account found');
      }
    }).catchError((exception) {
      if (exception is MsalMobileException) {
        logMsalMobileError(exception);
      } else {
        print('exception occurred');
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        home: new Scaffold(
      body: Builder(
        builder: (context) => Stack(
          fit: StackFit.expand,
          children: <Widget>[
            Container(
              width: MediaQuery.of(context).size.width,
              height: MediaQuery.of(context).size.height,
              child: Image.asset('assets/landing.webp',
                  fit: BoxFit.fill,
                  color: Color.fromRGBO(255, 255, 255, 0.6),
                  colorBlendMode: BlendMode.modulate),
            ),
            Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                SizedBox(height: 10.0),
                Container(
                  width: 130.0,
                  child: Align(
                      alignment: Alignment.center,
                      child: RaisedButton(
                        shape: RoundedRectangleBorder(
                            borderRadius: new BorderRadius.circular(30.0)),
                        color: Color(0xffffffff),
                        child: Row(
                          mainAxisAlignment: MainAxisAlignment.start,
                          children: <Widget>[
                            isSignedIn
                                ? Future.delayed(Duration.zero, () {
                                    Navigator.of(context).pushReplacement(
                                        MaterialPageRoute(
                                            builder: (context) => NavScreen()));
                                  })
                                : RaisedButton(
                                    child: Text("Sign In"),
                                    onPressed: handleSignIn,
                                  ),
                          ],
                        ),
                      )),
                )
              ],
            ),
          ],
        ),
      ),
    ));
  }
}

I don't know how to resolve this issue

flutter
dart
asked on Stack Overflow Nov 9, 2020 by blackbird • edited Nov 9, 2020 by blackbird

1 Answer

1

You are passing a function Future instead of Widget which is causing this error.

isSignedIn
      ? Future.delayed(Duration.zero, () {  // <---- This is not a widget
            Navigator.of(context).pushReplacement(
                MaterialPageRoute(
            builder: (context) => NavScreen()));
        })
        : RaisedButton(
        child: Text("Sign In"),
        onPressed: handleSignIn,
    ),

Instead of doing this, you can use the Visibility widget to hide/show your "Sign In" button & using the bool isSignedIn, you can handle the navigation code.

Visibility(
  visible: !isSignedIn,
  child: RaisedButton(
    child: Text("Sign In"),
    onPressed: handleSignIn,
  ),
),

You should handle the navigation inside the initState method of your StatefulWidget which would look something like this:

@override
void initState() {
  super.initState();
  signInNavigation();
}

Future<void> signInNavigation() async {
  // isSignedIn = await yourMethodWhichReturnsSignInStatus(); <-- Replace this with your method

  if(isSignedIn) {
    // Your navigation code
    Navigator.of(context).pushReplacement(
                MaterialPageRoute(
            builder: (context) => NavScreen()));
  }
}
answered on Stack Overflow Nov 9, 2020 by Ravi Singh Lodhi

User contributions licensed under CC BY-SA 3.0