21
loading...
This website collects cookies to deliver better user experience
Disclaimer - This article is not about how to set up cloud firestore. firebase.flutter.dev is a good place to learn about that. This article is about an issue I face personally while using Firebase Cloud Firestore, and what I do to make life a little easier!
Map<String, dynamic>
object. There are quite a few downsides to it.data
field of the first achievement
of the first friend
, and also the name
of the first friend
.Future<Map<String, dynamic>?> getDataTheUsualWay(String document) async {
final _data =
(await firestoreInstance.collection('users').doc(document).get())
.data();
return _data;
}
FutureBuilder
, this is handled in the following manner....
FutureBuilder(
future: getDataTheUsualWay('ENYMl6A76UTENuQ9fnOi'),
builder:(BuildContext context,
AsyncSnapshot<Map<String, dynamic>?> snapshot){
return snapshot.connectionState != ConnectionState.done
? Center(child: CircularProgressIndicator())
: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisSize: MainAxisSize.max,
children: [
Text(
'Data handled as how all other tutorials say '),
Text(
'Name is ${snapshot.data!['people']['friends'][0]['name']}'),
Text(snapshot.data!['people']['friends'][0]
['achievements'][0]['data']),
Text(snapshot.data!['people']['friends'][0]
['achievements'][0]['type']),
],
),
);
}
)
snapshot.data!['people'['friends'][0]['achievements'][0]['data']
. Any typos, or a wrong data type will result in an error. Because of which you will have to keep referring back to the database, hence slowing you down considerably..withConverter()
. What this does is that instead of dealing in Map<String, dynamic>
, this method will deal in terms of an object of a serializable class. Didn't get it? Just follow along!var firestoreInstance = FirebaseFirestore.instance;
final _data = await firestoreInstance
.collection('users')
.doc('*replae with document id*')
.get();
print(json.encode(_data.data()));
{
"achievements":[
{
"data":"Strong meme game",
"type":"non-academic"
},
{
"data":"Cleared multiple subjects without submitting assignments",
"type":"academic"
}
],
"alive":true,
"name":"Chinmay Kabi",
"people":{
"friends":[
{
"achievements":[
{
"data":"Funny name",
"type":"non-academic"
}
],
"name":"Mr Thingumbob"
}
]
},
"age":69
}
user.dart
in my case.Future<User?>? getDataTheBetterWay(String document) async {
final _data = await firestoreInstance
.collection('users')
.doc(document)
.withConverter<User>(
fromFirestore: (snapshot, _) =>
userFromJson(json.encode(snapshot.data())),
toFirestore: (model, _) => json.decode(userToJson(model)))
.get();
return _data.data();
}
User
object. Getting the name of this user is as simple as user.name
, which the IDE will give you code suggestions for the moment you have typed user.n
. We can display the same data we had shown before in this way.FutureBuilder(
future: getDataTheBetterWay('ENYMl6A76UTENuQ9fnOi'),
builder: (BuildContext context, AsyncSnapshot<User?> snapshot) {
return snapshot.connectionState != ConnectionState.done
? Center(child: CircularProgressIndicator())
: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisSize: MainAxisSize.max,
children: [
Text('Data handled using my method'),
Text(
'Name is ${snapshot.data!.people.friends[0].name}'),
Text(snapshot
.data!.people.friends[0].achievements[0].data),
Text(snapshot
.data!.people.friends[0].achievements[0].type),
],
),
);
},
),
snapshot.data!.people.friends[0].achievements[0].data
will be effortless for you because code suggestions! Also this ensures type safety, so a string cannot magically turn into a number(sorry JS people!). Such an arrangement is helpful when you have to refer a lot of fields of a document. But it only gets better!type
field of the first achievements
of the first friends
Future<void> updateDataTheUsualWay(String document, String data) async {
final userRef = firestoreInstance.collection('users').doc(document);
final userData = (await userRef.get()).data();
var friendsList = userData!['people']['friends'];
friendsList[0]['achievements'][0]['type'] = data;
await userRef.update({
"people": {"friends": friendsList}
});
print(data);
}
friends
array. We have a copy of the mutated array. But we cannot pass it directly. Because it is nested inside people
, we need to pass this map to the update()
.{
"people":{
"friends":friendsList
}
}
Future<void> updateDataTheBetterWay(String document, User user) async {
final userRef = firestoreInstance
.collection('users')
.doc(document)
.withConverter<User>(
fromFirestore: (snapshot, _) =>
userFromJson(json.encode(snapshot.data())),
toFirestore: (model, _) => model.toJson());
await userRef.set(user);
}
User? user =await getUserTheBetterWay('ENYMl6A76UTENuQ9fnOi');
user!.people.friends[0].achievements[0].type = data;
updateDataTheBetterWay('ENYMl6A76UTENuQ9fnOi', user);
.withConverter()
in any of the tutorials for Firebase Cloud Firestore. I hope this article acts as a primer for this, and makes working with Firebase Cloud Firestore a bit easier. This is by no means an in-depth article about .withConverter()
, so feel free to comment about anything you want me to cover more about this in another article!21