I see a lot of people with very similar problems, but nothing I try works.
I have a list of favorited ideas. Whenever I click in a button inside the ideaItem, it should get removed from the list.
When I delete any ideaItem, the last one from the screen gets always removed, instead of the one I clicked on. My FavoriteIdeasListView seems to update correctly the items count, this means that the attached List works, but the UI is not redrawing the ideaItems.
At the beginning I had the delete functionality directly on ideaItem, I read I should do a VoidCallback and handle deletion from the List itself, so it would notice the change. It didn't work
I also tried with a Stream Builder, so the stream would notify the ListView to refresh. Also it didn't work
I try calling SetState all the time and it's not reloading, it only builds the list at the beginning on the initialState.
class FavoritesList extends StatefulWidget {
FavoritesList({Key key}) : super(key: key);
@override
_FavoritesListState createState() => _FavoritesListState();
}
class _FavoritesListState extends State<FavoritesList> {
List<Idea> _favorites = [];
@override
void initState() {
super.initState();
favoritesInitialState();
}
Future <void> favoritesInitialState() async {
List<Idea> ideas = await IdeasDB.db.ideas();
setState(() {
_favorites = ideas;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Favorites')),
body: Center(
child: ListView.builder(
itemCount: _favorites.length,
itemBuilder: (context, index) {
final idea = _favorites[index];
return IdeaItem(
idea: idea,
onFavoriteToggle: () => deleteFromFavorites(idea),
);
},
),
)
);
}
void deleteFromFavorites(Idea idea) async {
await IdeasDB.db.deleteIdea(idea.url);
List<Idea> newIdeas = await IdeasDB.db.ideas();
setState(() {
this._favorites = newIdeas;
});
}
}
I can see only two possible options for why this happens.
First one is obvious, your IdeasDB.db.deleteIdea(idea.url);
doesn't delete correct idea from DB;
The second one is less obvious, it's because your Element Tree couldn't recognize what's a widget you are trying to delete. It happens only with Stateful Widgets as your IdeaItem
could be.
Solution then is to use key
attribute for your IdeaItem
widget
like this:
ListView.builder(
itemCount: _favorites.length,
itemBuilder: (context, index) {
final idea = _favorites[index];
return IdeaItem(
key: ValueKey(idea.url) // or UniqueKey()
idea: idea,
onFavoriteToggle: () => deleteFromFavorites(idea),
);
},
),
and in your IdeaItem
widget you have to pass that key to your parent Stateful widget
like in this example:
class IdeaItem extends StatefulWidget {
final Idea idea;
Function onFavoriteToggle;
IdeaItem({Key key, this.idea, this.onFavoriteToggle}) : super(key: key);
@override
_IdeaItemState createState() => _IdeaItemState();
}
Try to change
onFavoriteToggle: () => deleteFromFavorites(index),
and then
void deleteFromFavorites( int index) async {
await IdeasDB.db.deleteIdea(idea.url);
setState(() {
this._favorites.removeAt(index);
});
}
See if it works. If yes, there is probably error on deleteIdea()
.
Also, you know which item should be deleted, so you don't need to await to reload the List from your db. await IdeasDB.db.ideas();
If you want to be sure you can wrap your code with Try catch
void deleteFromFavorites(int index) async {
try {
await IdeasDB.db.deleteIdea(idea.url);
setState(() {
this._favorites.removeAt(index);
});
} catch (_) {
print('ERROR');
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With