0

I want to create a profil page where I just display informations from the user, but I have trouble to reach the data. When I want to use my variable user it display 'Instance of Future<Map<String, dynamic>>'

If I put the 'Widget build' in async I have an error message who told me : ProfileScreen.build' ('Future Function(BuildContext)') isn't a valid override of 'StatelessWidget.build' ('Widget Function(BuildContext)').

class ProfileScreen extends StatelessWidget {
  ProfileScreen({super.key});

  @override
  Widget build(BuildContext context) {
    final user = displayUser();
    return Scaffold(
        appBar: AppBar(
          title: Text('Profile'),
        ),
        body: Align(
          alignment: Alignment.topLeft,
          child: Column(
              mainAxisAlignment: MainAxisAlignment.start,
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Align(
                  alignment: Alignment.topLeft,
                  child: Column(children: [
                    Text('Prénom :${user}\nNom :\nEmail :',
                        textWidthBasis: TextWidthBasis.longestLine),
                  ]),
                )
              ]),
        ),
        persistentFooterButtons: [
          SignOutButton(),
          BottomNavBar(),
        ]);
  }

  // Get user informations
  Future<Map<String, dynamic>> displayUser() async {
    final User? currentUser = FirebaseAuth.instance.currentUser;
    late final userUid = currentUser?.uid;
    late final ref = FirebaseDatabase.instance.ref();
    final resSnapshot = await ref.child('/utilisateur/' + userUid!).get();
    final Map<String, dynamic> user = {};

    if (resSnapshot.exists) {
      user['id'] = userUid;
      for (var value in resSnapshot.children) {
        String key = value.key as String;
        var val = value.value;
        user[key] = val;
      }
    } else {
      print('No data available.');
    }
    print(user); // This print display exactly the informations I want.
    return user;
  }
}


Thanks for your help.

1
  • What do you want to display and where ? Commented Jan 3, 2023 at 11:43

3 Answers 3

1

Your displayUser is async function and you can't call it inside build method, you need to use FutureBuilder like this:

@override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Profile'),
      ),
      body: FutureBuilder<Map<String, dynamic>>(
        future: displayUser(),
        builder: (context, snapshot) {
          switch (snapshot.connectionState) {
            case ConnectionState.waiting:
              return Text('Loading....');
            default:
              if (snapshot.hasError) {
                return Text('Error: ${snapshot.error}');
              } else {
                Map<String, dynamic> user = snapshot.data ?? {};

                return Align(
                  alignment: Alignment.topLeft,
                  child: Column(
                    mainAxisAlignment: MainAxisAlignment.start,
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: [
                      Align(
                        alignment: Alignment.topLeft,
                        child: Column(
                          children: [
                            Text(
                              'Prénom :${user}\nNom :\nEmail :',
                              textWidthBasis: TextWidthBasis.longestLine,
                            ),
                          ],
                        ),
                      )
                    ],
                  ),
                );
              }
          }
        },
      ),
      persistentFooterButtons: [
        SignOutButton(),
        BottomNavBar(),
      ],
    );
  }

You can customize loading and error state to what you want.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks a lot, I understand a lot of thing when I see your code ! <3
0

You can load the user in the initstate and then set user using setstate

class ProfileScreen extends StatefulWidget {
  const ProfileScreen({super.key});

  @override
  State<ProfileScreen> createState() => _ProfileScreenState();
}

class _ProfileScreenState extends State<ProfileScreen> {
  Map<String, dynamic>? user;

  @override
  void initState() {
   final User? currentUser = FirebaseAuth.instance.currentUser;
    late final userUid = currentUser?.uid;
    late final ref = FirebaseDatabase.instance.ref();
    final resSnapshot = await ref.child('/utilisateur/' + userUid!).get();
    Map<String, dynamic> temp = {};

    if (resSnapshot.exists) {
      temp['id'] = userUid;
      for (var value in resSnapshot.children) {
        String key = value.key as String;
        var val = value.value;
        temp[key] = val;
      }
    } else {
      print('No data available.');
    }
    print(temp);
    setState((){
    user =temp 
});
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
          child:
              user != {} ? Text(user.toString()!) : const CircularProgressIndicator()),
    );
  }
}

2 Comments

calling await in initState makes your page load laggy. because it pause the ui thread.
@eamirho3ein totally agree. I was just letting the questionnaire know how to do without futurebuilder
0

change StatelessWidget to StatefulWidget because userInteract on profileScreen, UserInteraction changes will show on firebase.

class ProfileScreen extends StatefulWidget{
  ProfileScreen({super.key});

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.