I am developing a backend using node.js
and express
and MongoDB
and socket.io
and in the front-end, I am using flutter
and dart
.
I am using emit
to emit data from backend to the flutter
app and it works fine and I can receive the message so the problem isn't in the backend.
when I receive that message I want to add it to a list and then setstate to refresh the build method to rebuild the build method but it fails and gives me that error:
[ERROR:flutter/lib/ui/ui_dart_state.cc(148)] Unhandled Exception: setState() called after dispose(): _NewsState#a696c(lifecycle state: defunct, not mounted)
E/flutter (11883): This error happens if you call setState() on a State object for a widget that no longer appears in the widget tree (e.g., whose parent widget no longer includes the widget in its build). This error can occur when code calls setState() from a timer or an animation callback.
E/flutter (11883): The preferred solution is to cancel the timer or stop listening to the animation in the dispose() callback. Another solution is to check the "mounted" property of this object before calling setState() to ensure the object is still in the tree.
E/flutter (11883): This error might indicate a memory leak if setState() is being called because another object is retaining a reference to this State object after it has been removed from the tree. To avoid memory leaks, consider breaking the reference to this object during dispose().
here is my code snippet to listen to events coming from backend:
Provider.of<IoProvider>(context).globalSocket.connect();
Provider.of<IoProvider>(context).globalSocket.on('posts', (data) {
if (data['action'] == 'add') {
setState(() {
postData.add(data['data']);
});
}
print('--emit--');
});
I am using this in the build method and I have declared the postData list at the top of the state class.
I am also using a future function inside the init state method to get the data from the backend and then setstate to make postData equal to the response data coming from the backend and its a success.
code snippet:
Future getPosts() async {
var data = await PostController().fetchPosts();
if (data['success'] == true) {
setState(() {
postData = data['posts'];
});
}
}
inside the initState:
@override
void initState() {
super.initState();
Future.delayed(Duration.zero, () {
getPosts(context);
});
_editingController = TextEditingController();
}
inside build method:
ListView.builder(
itemCount: postData.length,
itemBuilder: (context , index) => PostView(postData[index]),
);
Update
after testing I found that the problem not happening in the first time a user navigates to that screen but in the other times it fails.
but how to solve it?
After too much searching, I figured out the problem is occurred by flutter itself as I was using a bottom navigation bar with four screens and they recall initstate each time I go to them after some time.
finally, I was able to solve this problem by using the indexed stack widget.
Thank you,