NoSuchMethodError: invalid member on null: '_get' - flutter

full error message:
The following JSNoSuchMethodError was thrown building FutureBuilder<DocumentSnapshot>(dirty, state: _FutureBuilderState<DocumentSnapshot>#dfc82):
NoSuchMethodError: invalid member on null: '_get'
it comes from this line : UserModel user = UserModel.fromDoc(snapshot.data); and it is in :
body: FutureBuilder(
future: usersRef.doc(widget.userId).get(),
builder: ( context, snapshot) {
List<Widget> children;
if (!snapshot.hasData) {
return Center(
child: CircularProgressIndicator(),
);
}
else if (snapshot.hasData) {
// print('user snapshot data is: ${snapshot.data}');
UserModel user = UserModel.fromDoc(snapshot.data);
model looks like :
factory UserModel.fromDoc(DocumentSnapshot doc) {
return UserModel(
id: doc.data()['id'],
name: doc.data()['name'],
username: doc.data()['username'],
password: doc.data()['password'],
profileImageUrl: doc.data()['profileImageUrl'],
email: doc.data()['email'] ,
userIds: doc.data()['userIds'] ?? '',
);
}
I tried downgrading the version of cloud_firestore but still don't work

As your error log tells, you are accessing some value on a null member.
It seems, the error lies in your factory method. In Flutter, to access all data from documentSnapshot in Map<String, dynamic> have to use doc.data.
Before doing that, we could check for the document existence within DocumentSnapshot using doc.exists. For further ref - https://firebase.flutter.dev/docs/firestore/usage/
I prefer to handle all connectionstate including error or else your screen would get stuck in CircularProgressIndicator and it's hard for user to know the reason.
if (snapshot.hasError) {
return Text("Something went wrong");
} else if (snapshot.connectionState == ConnectionState.done) {
Map<String, dynamic> data = snapshot.data.data;
return Widget;
} else {
return Center(
child: CircularProgressIndicator());
}
Another case: If no document exists in firestore, the read (snapshot.data) will return null. However this null case internally handled by the futurebuilder connectionState. As per your debug result, since the snapshot.data has DocumentSnapshot, it didn't cause the error.

Related

How to get values inside _JsonDocumentSnapshot?

Flutter Streambuilder code below runs without error and returns (screenshot at bottom):
ID: AzFdOO9WsFaFbTxTQsuo
Data: Instance of '_JsonDocumentSnapshot'
How do I get to the values inside the _JsonDocumentSnapshot and display them in the Text() widget?
For instance, there's a string field called "name", but I can't figure out how to get to it.
StreamBuilder(
stream: FirebaseFirestore.instance
.collection("groceries")
.doc(widget.docId)
.snapshots(),
builder: (context, streamSnapshot) {
if (streamSnapshot.connectionState == ConnectionState.waiting) {
return const Text("Loading");
} else if (streamSnapshot.hasData) {
return Text("ID: ${widget.docId}\n"
"Data: ${streamSnapshot.data}");
} else {
return const Text("No Data");
}
}
)
Thanks for your help!
the following Stream, return an object with a type of DocumentSnapshot :
FirebaseFirestore.instance.collection("groceries").doc(widget.docId).snapshots();
and that type contains the document snapshot, and also contains more additional information about the document.
so in order to get the JSON Map<String, dynamic> which represents the data of the Firestore document, you need to call data() on the result of the snapshot.data(), so you need to try the following:
StreamBuilder<DocumentSnapshot>(
stream: FirebaseFirestore.instance
.collection("groceries")
.doc(widget.docId)
.snapshots(),
builder: (BuildContext context, AsyncSnapshot<DocumentSnapshot> streamSnapshot) {
if (streamSnapshot.connectionState == ConnectionState.waiting) {
return const Text("Loading");
} else if (streamSnapshot.hasData) {
return Text("ID: ${widget.docId}\n"
"Data: ${streamSnapshot.data.data()}"); // added data()
} else {
return const Text("No Data");
}
}
)
now it should show the Map<String, dynamic> object which contains your document data in the Text widget.
hope this helps.
In your code example streamSnapshot.data is an Object or a dynamic type variable.
To access the json value of your data, you have to specify the key corresponding to your value.
streamSnapshot.data['banana']

Flutter type 'Future<dynamic>' is not a subtype of type 'Widget' error

what I want to do is to pull some data from the docs where the logged in user is email from the collection named Repair. I created a function for this. But I'm getting the - type 'Future' is not a subtype of type 'Widget' - error.
getCustomerRepairLog() async {
final user = FirebaseAuth.instance.currentUser!;
var _repairLogs = await FirebaseFirestore.instance.collection('Repair').get();
for (var eleman in _repairLogs.docs) {
if (eleman.data()['email']! == user.email) {
return Container(
child: Column(
children: [
Text("$eleman.data()['description']"),
],
),
);
}
}
return Text('Loading');
}
I want to use it as getCustomerRepairLog() in Column. Can you help me?
You need to use FutureBuilder for future method.Create state variable to avoid recalling evrytime the state is build.
final user = FirebaseAuth.instance.currentUser!; //better do a null check 1st
late final _repairLogs = FirebaseFirestore.instance.collection('Repair').get();
And your method will be like
Widget getCustomerRepairLog() {
return FutureBuilder(
future: _repairLogs,
builder: (context, snapshot) {
if (snapshot.hasData) {
List<Widget> items = [];
final data = snapshot.data?.docs;
if (data == null) return Text("got null");
for (final eleman in data) {
if (eleman.data()['email']! == user.email) {
items.add(Text("${eleman.data()['description']}"));
}
}
return CircularProgressIndicator();
},
);
}
Find more about FutureBuilder

type '_JsonQuerySnapshot' error occured while using firestore QuerySnapShots

I think I got used to using DocumentSnapshot, without using any ordering or filtering.
Now I am making a query streamer using the code :
Stream<QuerySnapshot> postStream_left = FirebaseFirestore.instance.collection('post')
.where('topic',isEqualTo: received_id)
.where('side',isEqualTo:'left')
.orderBy('like')
.snapshots();
Stream<QuerySnapshot> postStream_right = FirebaseFirestore.instance.collection('post')
.where('topic',isEqualTo: received_id)
.where('side',isEqualTo:'right')
.orderBy('like').snapshots();
return StreamBuilder(stream:postStream_left,builder: (context,snapshot_l)
{
if(!snapshot_l.hasData){
return CircularProgressIndicator();
}
return StreamBuilder(stream:postStream_right,builder: (context,snapshot_r)
{
if(!snapshot_r.hasData){
return CircularProgressIndicator();
}
final documents_l = snapshot_l.data as Map<String,dynamic>; // Here is where I am stuck
final documents_r = snapshot_r.data as Map<String,dynamic>;
print('afepwmcakodepwxa.ofpe,[wambotpmwa');
print(documents_l);
print(documents_r);
return CircularProgressIndicator();
}
);
}
);
What I want to do is show the data of postStream_left and postStream_right in two listview at the same time. However I donot know how to parse the data of each QuerySnapshot, since they did not work with code that works for Documentsnapshot.
type '_JsonQuerySnapshot' is not a subtype of type 'Map<String, dynamic>' in type cast
Here is the error I got but flutter does not tell me how I should cast the data.
Please tell me what to do and thank you very much.
Answer was simple. Defining the type of streambuilder and snapshot.docs clearly solved the problem. I leave the answer for my own study and for someone suffering like me.
StreamBuilder<QuerySnapshot<Map<String, dynamic>>>(
stream: FirebaseFirestore.instance.collection('post')
.where('topic',isEqualTo: received_id).where('side',isEqualTo:'left')
.orderBy('like').snapshots(),
builder: (BuildContext context, snapshot){
if (snapshot.data == null) {
return Center(child: CircularProgressIndicator());
}
else{
final List<QueryDocumentSnapshot<Map<String, dynamic>>> docs = snapshot.data!.docs;

Flutter Firestore returns error without any problem in the code

The following code returns error "NoSuchMethodError"
StreamBuilder(
stream: SalaryService.getSingle(),
builder: (_, snapshot) {
if (snapshot.data() != null) {
print('step 3');
return Text(
snapshot.data['value'].toString(),
);
} else {
return Text(
"Nil",
);
}
},
),
class SalaryService {
static Stream<DocumentSnapshot> getSingle() {
Stream<DocumentSnapshot> snapshot = FirebaseFirestore.instance
.doc(userId + '/salary' + todayYM)
.snapshots();
snapshot.forEach(
(element) {
// prints all the documents available
// in the collection
print(element.data().toString());
// print((element.data() != null).toString());
},
);
return snapshot;
}
}
The cloudstore document does not exist to begin with until the user updates his salary hence the if else used.
P.S.: I am a rookie
Two things:
It is best practice to check whether the QueryDocumentSnapshot returned has data, plus check whether the document reference exists first by casting it as a DocumentSnapshot as opposed to pull the data straight up, as in:
if (snapshot.hasData && (snapshot.data as DocumentSnapshot).exists) { // ... }
you cannot pull the properties out of the snapshot like snapshot.data['field'] without pulling the data out first as a Map<String, dynamic>; you at least have to do first is snapshot.data() (after checking that it exists), then pull the fields out of the returned map, as in:
Map<String, dynamic> docData = (snapshot.data as DocumentSnapshot).data() as Map<String, dynamic>;
print(docData['value']);
Check this Gist for the full code (replace with your Firebase config settings at the top if you want to test it by running it on DartPad.dev.

Flutter FutureBuilder always return null

FutureBuilder keep returning null even when the http request successfully fetch the data from api.
I use json_serializable and freezed package in my data model, is this error related to them or it is purely coming from flutter/dart?
Http request
Future<VitalSignResponse> getLatestVitalSign(String medicalNo) async {
final String url = Api.baseUrl +
'VitalSignByMedicalNoLatest?AccessKey=${Api.accessKey}&MedicalNo=$medicalNo';
Response res = await Dio().get(url);
print('api res: ${res.data}'); // 'api res: the correct data from api'
print('serialize: ${VitalSignResponse.fromJson(json.decode(res.data))}'); // print out nothing
return VitalSignResponse.fromJson(json.decode(res.data));
}
data model
#freezed
abstract class VitalSignResponse with _$VitalSignResponse {
#JsonSerializable(explicitToJson: true)
const factory VitalSignResponse(
final String status,
final String errorCode,
final List<VitalSign> data,
) = _VitalSignResponse;
factory VitalSignResponse.fromJson(Map<String, dynamic> json) =>
_$VitalSignResponseFromJson(json);
}
future builder logic
FutureBuilder(
future: service.getLatestVitalSign(patientBloc.patient.medicalNo),
builder: (
BuildContext context,
AsyncSnapshot snapshot,
) {
print(snapshot.data); // null
if (snapshot.connectionState == ConnectionState.waiting)
return Center(child: CircularProgressIndicator());
if (snapshot.hasData) {
// show data
}
return Container();
},
),
I simply forgot to run my project with debugging
i leave the question here as a personal reminder and for new developer out there to not making the same mistake i did. And for my friends to laugh at me haha