Home > Enterprise >  Proper async/await use for unique Username check to Firestore database
Proper async/await use for unique Username check to Firestore database

Time:10-24

I have a Flutter app with a "Create Account" form that has a field for Username. Upon entering a username and hitting the "Submit" button, my validator functions run for the form. I would like to query my Firestore database and ensure that the username entered isn't already taken.

My validator (in the Username form):

validator: (value) {
  Future<bool> usernameTaken = uniqueCheck(value);
  if (usernameTaken) {
    return 'Username is already taken!';
  } else {
    return null;
  }

My uniqueCheck function:

  Future<bool> uniqueCheck(String? value) async {
    bool alreadyTaken = false;
    var snapshot = await FirebaseFirestore.instance
      .collection('users')
      .where('username', isEqualTo: value)
      .get();
    snapshot.docs.forEach((result) {
      alreadyTaken = true;
    });
    return alreadyTaken;
  }

The trouble is my validator finishes before my uniqueCheck function can return with the proper result (such as if the username is taken and usernameTaken is true. I thought await would fix this, but apparently not.

What am I doing wrong here?

CodePudding user response:

Try this:

validator: (value) async {
  Future<bool> usernameTaken = await uniqueCheck(value);
  if (usernameTaken) {
    return 'Username is already taken!';
  } else {
    return null;
  }
}

CodePudding user response:

SOLUTION: I figured it out. Validators can't be async so the solution was to call the uniqueCheck function in the onPressed function of the Submit button. I could then properly await to see if the email was taken and then I called setState(){} to redraw the screen.

onPressed: () async {
      emailTaken = await uniqueCheck(emailKey.currentState!.value);
      setState(() {});
      if (formKey.currentState!.validate()) {
        formKey.currentState?.save();
        // {... add to database ...}
        // {... navigate to successful sign-in screen ...}
      }
    },

Note that the emailTaken bool is global to this scope so that when setState(){} is called, the validator in the email field will pick it up as true.

Email field form validator function:

validator: (value) {
      if ((value!.isEmpty) | !(value.contains('@'))) {
        return 'Please enter a valid email address.';
      } else if (emailTaken) {
        return 'Email is already taken!';
      } else {
        return null;
      }
    }
  • Related