Home > Software engineering >  Flutter | Unhandled Exception: Bad state: No element using 'firstWhere' and 'orElse&#
Flutter | Unhandled Exception: Bad state: No element using 'firstWhere' and 'orElse&#

Time:11-27

I am having trouble understanding how to return null using: orElse: () => null My method is the following:

@override
  Future<People> searchPeople({required String email}) async {
    var user = auth.FirebaseAuth.instance.currentUser;
    final docs = await FirebaseFirestore.instance
        .collection('users')
        .doc(user!.email)
        .collection('people')
        .where('hunting', isEqualTo: email)
        .get();

    final docData = docs.docs.map((doc) {
      return People.fromSnapshot(doc);
    });

    var res = docData.firstWhere(
      (element) => element.hunting == email,
      orElse: () => null, // The return type 'Null' isn't a 'People', as required by the closure's 
    );
    print(res);
    return res;
  }

The problem is that it throws the error: "The return type 'Null' isn't a 'People', as required by the closure's"

I have already read many answers here but all examples and answers apply only to return type string, int, etc... How to handle null when a type is an object (People)? Already tried to use collection: firstWhereOrNull but the error persists...

Is something that I should change in my model?

class People extends Equatable {
  String? hunting;
  String? username;
  String? persona;

  People({
    this.hunting,
    this.username,
    this.persona,
  });

  @override
  List<Object?> get props => [hunting, username, persona];
  static People fromSnapshot(DocumentSnapshot snapshot) {
    People people = People(
      hunting: snapshot['hunting'],
      username: snapshot['username'],
      persona: snapshot['persona'],
    );
    return people;
  }

  Map<String, dynamic> toMap() {
    return {
      'hunter': hunting,
      'username': username,
      'persona': persona,
    };
  }
}

Thanks for any help!

CodePudding user response:

The signature for Iterable<E>.firstWhere is:

E firstWhere(bool test(E element), {E orElse()?})

That is, Iterable<E>.firstWhere must return an E. It cannot return E?. If E is non-nullable, then .firstWhere cannot return null. As explained by the Dart Null Safety FAQ, if you want to return null from .firstWhere, you instead should use the firstWhereOrNull extension method from package:collection.

However, your searchPeople method is declared to return a Future<People>, not a Future<People?>. Even if you use firstWhereOrNull, your searchPeople function cannot legally return null anyway. You therefore would need to additionally do one of:

  • Changing the return type of searchPeople (and in all of the base classes).
  • Picking some non-null value to return instead of null.
  • Throwing an exception.

CodePudding user response:

Try doing this instead:

var res = docData.firstWhere((element) => element.hunting == email, orElse: () => People(username: 'Not Found', hunting: 'Not Found', persona: 'Not Found'));
  • Related