Search code examples
flutterdartflutter-provider

Why Provider is not giving the initialized value instead of expected one?


I'm trying to display a document field value from firestore and want to display it on other pages using the provider.

This is my code inside the provider file:

class UserState extends ChangeNotifier {
  
  String userName = 'default error';

   Future<void> getName() async {
    await FirebaseFirestore.instance
        .collection("Users")
        .doc(FirebaseAuth.instance.currentUser!.uid)
        .get()
        .then((value) {
      userName = (value.data()?[' uname'] ?? "Default userName");
      print(userName);
    });
    notifyListeners();
  }
}

Here the correct userName value is getting printed using print statement, but when I try to pass it through the provider it is showing the initialized string value default error which I provided for null safety. This is the screen where I want to display the variable userName :


class testscreen extends StatefulWidget {
  const testscreen({Key? key}) : super(key: key);
  _testscreenState createState() => _testscreenState();
}

class _testscreenState extends State<testscreen> {
  @override
  Widget build(BuildContext context) {

    Provider.of<UserState>(context, listen: false).getName();
    final String name = Provider.of<UserState>(context).userName;
    return Scaffold(body: Text(name));
  }
}

How can I show the right value instead of initialized value for userName?What's wrong with my code?


Solution

  • There are some fixes in the code.

    1. notifyListeners() are not waiting for the fetch to complete
     await FirebaseFirestore.instance
            .collection("Users")
            .doc(FirebaseAuth.instance.currentUser!.uid)
            .get()
            .then((value) {
          userName = (value.data()?[' uname'] ?? "Default userName");
          print(userName);
          notifyListeners(); 👈 Try adding the notifyListeners() here
        });
      }
    
    1. Remove the provider() call from within the bluid method
    class testscreen extends StatefulWidget {
      const testscreen({Key? key}) : super(key: key);
      _testscreenState createState() => _testscreenState();
    }
    
    class _testscreenState extends State<testscreen> {
      @override
      void initState() {
        super.initState();
         Provider.of<UserState>(context, listen: false).getName();👈 Call getName here
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(body: Text( Provider.of<UserState>(context).userName)); 👈 Call it this way
      }
    }