0

I'm using provider to fetch current user's data from firebase. in the UI I have 2 types of users and the UI should change based on that value.

the problem is when I login with a type 1 user. then logout and login with a type 2 user I get the UI that's declared for type 1...

here's my provider:

class UserProvider extends ChangeNotifier {
  User? _user;

  User? get user => _user;

  String userid = Auth().currentUser!.uid;

  Future<void> fetchUser() async {
    final snapshot =
        await FirebaseFirestore.instance.collection('users').doc(userid).get();

    _user = User.fromFirestore(snapshot);
    notifyListeners();
  }
}

for the MainPage.dart that shows the UI here's my code:

class MainPage extends StatefulWidget {
  const MainPage({super.key});
  static String id = "MainPage";

  @override
  State<MainPage> createState() => MainPageState();
}

class MainPageState extends State<MainPage> {
  @override
  void initState() {
    super.initState();
    final userProvider = context.read<UserProvider>();
    userProvider.fetchUser();
    final artProvider = context.read<ArtProvider>();
    artProvider.fetchArts();
  }

  void _getCurrentpage(value) async {
    switch (value) {
      case 0:
        setState(() {
          _bottomNavIndex = value;
          _child = const HomePage();
        });
        break;
      case 1:
        setState(() {
          _bottomNavIndex = value;
          _child = const ProfilePage();
        });
        break;
    }
  }

  Widget _child = const HomePage();

  var iconList = <IconData>[
    FontAwesomeIcons.house,
    FontAwesomeIcons.solidUser,
  ];

  var _bottomNavIndex = 0;
  bool loading = true;

  static final loadingWidget = LoadingAnimationWidget.flickr(
    leftDotColor: const Color(0xff9FFFE4),
    rightDotColor: const Color(0xFFFF99CC),
    size: 100,
  );
  static final loadingWidgetSmall = LoadingAnimationWidget.flickr(
    leftDotColor: const Color(0xff9FFFE4),
    rightDotColor: const Color(0xFFFF99CC),
    size: 60,
  );

  static final loadingWidgetSmallest = LoadingAnimationWidget.flickr(
    leftDotColor: const Color(0xff9FFFE4),
    rightDotColor: const Color(0xFFFF99CC),
    size: 20,
  );

  @override
  Widget build(BuildContext context) {
    return SafeArea(
      child: Consumer<UserProvider>(
        builder: (context, provider, child) {
          return Scaffold(
            body: _child,
            floatingActionButton: provider.user != null
                ? provider.user!.pending == false
                    ? FloatingActionButton(
                        backgroundColor: Theme.of(context).primaryColor,
                        onPressed: () {
                          Navigator.pushNamed(context, AddArtPage.id);
                        },
                        shape: const RoundedRectangleBorder(
                          borderRadius: BorderRadius.all(
                            Radius.circular(50.0),
                          ),
                        ),
                        child: const Icon(
                          Icons.qr_code_2,
                          color: Colors.white,
                        ),
                      )
                    : SpeedDial(
                        icon: Icons.menu,
                        backgroundColor: Theme.of(context).primaryColor,
                        foregroundColor: Colors.white,
                        overlayColor: Colors.transparent,
                        elevation: 20,
                        overlayOpacity: 0.4,
                        direction: SpeedDialDirection.up,
                        spaceBetweenChildren: 5,
                        animatedIcon: AnimatedIcons.menu_close,
                        children: [
                          SpeedDialChild(
                            onTap: () {
                              Navigator.pushNamed(context, QRViewExample.id);

                              // Navigator.of(context).push(MaterialPageRoute(
                              //   // builder: (context) => const QRViewExample(),
                              // ));
                            },
                            elevation: 20,
                            backgroundColor: const Color(0xFF1bdcff),
                            child: const Icon(Icons.qr_code),
                            label: 'Scan QR code',
                          ),
                          SpeedDialChild(
                            onTap: () {
                              Navigator.pushNamed(context, AddArtPage.id);
                              // Navigator.pushNamed(context, '/canvas');
                            },
                            elevation: 20,
                            backgroundColor: const Color(0xFF1bdcff),
                            child: const Icon(Icons.add_photo_alternate),
                            label: 'Add a new art piece',
                          ),
                        ],
                      )
                : Container(),
            floatingActionButtonLocation:
                FloatingActionButtonLocation.centerDocked,
            bottomNavigationBar: AnimatedBottomNavigationBar(
              backgroundColor: Colors.white,
              activeColor: Theme.of(context).primaryColor,
              inactiveColor: Colors.black38,
              height: 60,
              icons: iconList,
              activeIndex: _bottomNavIndex,
              gapLocation: GapLocation.center,
              notchSmoothness: NotchSmoothness.softEdge,
              onTap: (value) {
                _getCurrentpage(value);
              },
            ),
          );
        },
      ),
    );
  }
}

Aymen Ziouche
  • 47
  • 3
  • 12

1 Answers1

0

You can listen to changes in user state, for example detect logout and login events. In the provider's constructor you can set up a listener like this:

UserProvider() {
  FirebaseAuth.instance.authStateChanges().listen((User? user) {
    // this will be called whenever the user signs out (`user` will be null)
    // or signs in, so you can implement your logic here, for example 
    // call `fetchUser`
  });
}

Two things:

  • It is not advised to call Future functions from initState, instead use a FutureBuilder.
  • Be careful with type User. It is Firebase's own user class. I don't know your what does User.fromFirestore function do but you might want to create an own class for user data to be fetched from Firestore.
Peter Koltai
  • 8,296
  • 2
  • 10
  • 20