Reputation: 93
I'm trying to add a check in my app via a StreamBuilder to show users different screens based upon if a user's document exists in Firestore. My code technically works but on hot reload, it shows my 'AddUser' screen for a couple of seconds before moving over to my 'UserHomeScreen'. I was wondering how to rectify this so the 'AddUser' screen does not show my 'AddUser' screen at all if the user document exists.
Here is my code:
class UserStream extends StatelessWidget {
const UserStream({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
FirebaseAuth auth = FirebaseAuth.instance;
String uid = auth.currentUser!.uid.toString();
return StreamBuilder<dynamic>(
stream: FirebaseFirestore.instance.collection('users').doc(uid).snapshots(),
builder: (context, snapshot) {
if (snapshot.hasData && snapshot.data!.exists) {
return const UserHomeScreen();
} else {
return AddUser(youtubeLink: '', bio: '', bioLink: '', displayName: '', instaLink: '', profilePhoto: '', tiktokLink: '', username: '',);
}
},
);
}
}
Upvotes: 0
Views: 635
Reputation: 19434
I think your solution is not a good practice. This is my solution.
You have to create some splash/landing screen to handle your logic.
class LandingPage extends StatefulWidget {
@override
_LandingPageState createState() => _LandingPageState();
}
class _LandingPageState extends State<LandingPage> {
final FirebaseAuth auth = FirebaseAuth.instance;
final FirebaseFirestore db = FirebaseFirestore.instance;
@override
void initState() {
super.initState();
String? uid = auth?.currentUser?.uid;
if(uid == null) {
Navigator.pushReplacement(context, MaterialPageRoute(builder: (_) => AddUser(youtubeLink: '', bio: '', bioLink: '', displayName: '', instaLink: '', profilePhoto: '', tiktokLink: '', username: '',)));
} else {
db.collection('users').doc(uid!).get().then((doc) {
var user = doc.data();
if(user != null) {
Navigator.pushReplacement(context, MaterialPageRoute(builder: (_) => UserHomeScreen()));
} else {
Navigator.pushReplacement(context, MaterialPageRoute(builder: (_) => AddUser(youtubeLink: '', bio: '', bioLink: '', displayName: '', instaLink: '', profilePhoto: '', tiktokLink: '', username: '',)));
}
}
});
}
}
@override
Widget build(BuildContext context) {
return Scaffold(); // some loading UI
}
Upvotes: 1
Reputation: 831
You could structure your builder like this:
builder: (context, snapshot) {
if (snapshot.hasData) {
if (snapshot.data!.exists){
return const UserHomeScreen();
} else {
return AddUser(youtubeLink: '', bio: '', bioLink: '', displayName: '', instaLink: '', profilePhoto: '', tiktokLink: '', username: '',);
}
} else {
return CircularProgressIndicator();
}
},
This way, you show a CircularProgressIndicator
while the snapshot is resolving. At this point, you don't know of your data exists or not.
As soon as the snapshot is resolved and you have information, whether your data exists, you can show the respective screen.
Upvotes: 2