List firstWhere Bad state: No element
Solution 1:
This will happen when there is no matching element, i.e. when a == b
is never true for any of the elements in list
and the optional parameter orElse
is not specified.
You can also specify orElse
to handle the situation:
list.firstWhere((a) => a == b, orElse: () => print('No matching element.'));
If you want to return null
instead when there is no match, you can also do that with orElse
:
list.firstWhere((a) => a == b, orElse: () => null);
package:collection
also contains a convenience extension method for the null
case (which should also work better with null safety):
import 'package:collection/collection.dart';
list.firstWhereOrNull((element) => element == other);
See firstWhereOrNull
for more information. Thanks to @EdwinLiu for pointing it out.
Solution 2:
firstWhere
retuns the newList which generated based on the condition
void main() {
List<String> list = ['red', 'yellow', 'pink', 'blue'];
var newList = list.firstWhere((element) => element == 'green',
orElse: () => 'No matching color found');
print(newList);
}
Output:
No matching color found
OR
void main() {
List<String> list = ['red', 'yellow', 'pink', 'blue'];
var newList = list.firstWhere((element) => element == 'blue',
orElse: () => 'No matching color found');
print(newList);
}
Output:
blue
If orElse not defined in the code and the wrong item gets search which doesn't exist in the list then it shows BadStateException
void main() {
List<String> list = ['red', 'yellow', 'pink', 'blue'];
var newList = list.firstWhere((element) => element == 'green');
print(newList);
}
Output:
Uncaught Error: Bad state: No element
Solution 3:
Now you can import package:collection
and use the extension method firstWhereOrNull
import 'package:collection/collection.dart';
void main() {
final myList = [1, 2, 3];
final myElement = myList.firstWhereOrNull((a) => a == 4);
print(myElement); // null
}
Solution 4:
The firstWhere()
implementation looks something like below:
E firstWhere(bool test(E element), {E orElse()?}) {
for (E element in this) {
if (test(element)) return element;
}
if (orElse != null) return orElse();
throw IterableElementError.noElement();
}
So as you can see, if the orElse
arg is defined the method will use that and will not throw any exception if none of the elements match the condition. So use the below code to handle the erro case:
list.firstWhere((element) => a == b, orElse: () => null); // To return null if no elements match
list.firstWhere((element) => a == b, orElse: () => print('No elements matched the condition'));
Solution 5:
On dart 2.10
there is a new feature called null-safety
and can do magic for you when you have a list of objects and you want to do something to one particular object's property:
class User {
String name;
int age;
User(this.name, this.age);
@override
String toString() {
return 'name:$name, age:$age';
}
}
void main() {
List<User?> users = [User("Ali", 20), User("Mammad", 40)];
print(users.toString()); // -> [name:Ali, age:20, name:Mammad, age:40]
// modify user age who it's name is Ali:
users.firstWhere((element) => element?.name == "Ali")?.age = 30;
print(users.toString()); // -> [name:Ali, age:30, name:Mammad, age:40]
// modify a user that doesn't exist:
users.firstWhere((element) => element?.name == "AliReza", orElse: ()=> null)?.age = 30; // doesn't find and works fine
print(users.toString()); // -> [name:Ali, age:30, name:Mammad, age:40]
}