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.
CodePudding user response:
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.
CodePudding user response:
change StatelessWidget to StatefulWidget because userInteract on profileScreen, UserInteraction changes will show on firebase.
class ProfileScreen extends StatefulWidget{ ProfileScreen({super.key});
CodePudding user response:
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()),
);
}
}