I'm actually having issues while working with Appwrite and Riverpod, Whenever I try to get the comments from the appwrite server, I get bad state: no element error.
This Error mostly appears when I click to get the comment on a post, and sometimes after clicking on the hot-reload the error will stop and again it will appear.
I don't know what I'm actually doing wrong
Below is my screenshot and code
ref.watch(getRepliesToPostProvider(widget.postModel!)).when(
data: (post) {
return ref.watch(getLatestPostProvider).when(
data: (data) {
if (data.events.contains(
'databases.*.collections.${Common.postCollection}.documents.*.create',
)) {
post.insert(0, PostModel.fromMap(data.payload));
} else if (data.events.contains(
'databases.*.collections.${Common.postCollection}.documents.*.update',
)) {
final startingIndex =
data.events[0].lastIndexOf('documents.');
final endIndex =
data.events[0].lastIndexOf('.update');
var postId = data.events[0]
.substring(startingIndex + 10, endIndex);
var newPost = post
.where((element) => element.id == postId)
.first;
final postIndex = post.indexOf(newPost);
post.removeWhere((element) => element.id == postId);
newPost = PostModel.fromMap(data.payload);
post.insert(postIndex, newPost);
}
return Expanded(
child: ListView.builder(
padding: const EdgeInsets.all(0),
shrinkWrap: true,
scrollDirection: Axis.vertical,
physics: const ClampingScrollPhysics(),
itemCount: post.length,
itemBuilder: (BuildContext context, int index) {
var disPost = post[index];
final latestPost =
PostModel.fromMap(data.payload);
bool isPostAlreadyPresent = false;
for (final postLoop in post) {
if (postLoop.id == latestPost.id) {
isPostAlreadyPresent = true;
break;
}
}
return ref
.watch(userDetailsProvider(
widget.postModel!.uid))
.when(
data: (user) {
return Padding(
padding: const EdgeInsets.only(
left: 8.0,
top: 2,
right: 8,
bottom: 2,
),
child: Row(
children: [
CircularProfileAvatar(
user.profile,
radius: 20,
backgroundColor:
Colors.transparent,
borderWidth: 2,
initialsText: Text(
"AD",
style: TextStyle(
color: colorWhite),
),
borderColor: colorWhite,
elevation: 5.0,
foregroundColor: Colors.brown
.withOpacity(0.5),
cacheImage: true,
imageFit: BoxFit.cover,
onTap: () {
print('adil');
},
showInitialTextAbovePicture:
false,
),
const SizedBox(
width: 15,
),
Expanded(
child: Text(disPost.text),
),
],
),
);
},
error: (error, stk) => Container(),
loading: () => Container());
},
),
);
},
error: (error, stk) => ErrorText(
error: error.toString(),
),
loading: () {
return Expanded(
child: ListView.builder(
padding: const EdgeInsets.all(0),
shrinkWrap: true,
scrollDirection: Axis.vertical,
physics: const ClampingScrollPhysics(),
itemCount: post.length,
itemBuilder: (BuildContext context, int index) {
var disPost = post[index];
return ref
.watch(userDetailsProvider(
widget.postModel!.uid))
.when(
data: (user) {
return Padding(
padding: const EdgeInsets.only(
left: 8.0,
top: 2,
right: 8,
bottom: 2,
),
child: Row(
children: [
CircularProfileAvatar(
user.profile,
radius: 20,
backgroundColor:
Colors.transparent,
borderWidth: 2,
initialsText: Text(
"AD",
style: TextStyle(
color: colorWhite),
),
borderColor: colorWhite,
elevation: 5.0,
foregroundColor: Colors
.brown
.withOpacity(0.5),
cacheImage: true,
imageFit: BoxFit.cover,
onTap: () {
print('adil');
},
showInitialTextAbovePicture:
false,
),
const SizedBox(
width: 15,
),
Expanded(
child: Text(disPost.text),
),
],
),
);
},
error: (error, stk) => Container(),
loading: () => Container());
}),
);
});
},
error: (error, stk) => ErrorText(
error: error.toString(),
),
loading: () => const Loader(),
),
Screenshot
You've highlighted the problem:
var newPost = post
.where((element) => element.id == postId)
.first;
This throws an error; as mentioned here, it happens because the where
didn't find anything matching.
You can reproduce this by running this:
final l = [1,2,3];
final e = l.where((e) => e == 0).first;
This could be happening because some Riverpod providers may not have finished fetching the data. It's important to be defensive and always handle the cases where something is missing.