I am trying to retrieve "comments" data from the API. But the main problem is I want to see the comments of the post according to the post I've selected or pressed instead of providing a static postId as the query parameter.
Here's my code:
Comment Model
class Comment {
int postId;
int id;
String name;
String email;
String body;
Comment({
required this.postId,
required this.id,
required this.name,
required this.email,
required this.body,
});
factory Comment.fromJson(Map<String, dynamic> json) {
return Comment(
postId: json['postId'],
id: json['id'],
name: json['name'],
email: json['email'],
body: json['body'],
);
}
}
Comment Provider (Riverpod and Dio used). Note that I've used postId = 1 as query parameter
final commentProvider = StateNotifierProvider<CommentProvider, List<Comment>>(
(ref) => CommentProvider());
List<Comment> commentList = [];
class CommentProvider extends StateNotifier<List<Comment>> {
CommentProvider() : super([]) {
getComments(postId: 1);
}
Future<void> getComments({required int postId}) async {
final dio = Dio();
try {
final response = await dio.get(Api.commentApi, queryParameters: {
'postId': postId,
});
state = (response.data as List).map((e) => Comment.fromJson(e)).toList();
commentList = state;
print(response.data);
} on DioError catch (err) {
print(err);
}
}
}
This is my main screen where I'm fetching the posts data from the API
Consumer(
builder: (context, ref, child) {
final posts = ref.watch(postProvider);
return ListView.builder(
itemCount: posts.length,
itemBuilder: (context, index) {
final data = posts[index];
return Container(
child: Column(
children: [
InkWell(
onTap: () {
Get.to(() => DetailScreen(), transition: Transition.zoom);
},
child: Container(
width: MediaQuery.of(context).size.width,
padding: EdgeInsets.all(AppPadding.p16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
CircleAvatar(
backgroundColor: Colors.grey[300],
radius: 13,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(data.userId.toString(), style: TextStyle(color: Colors.black, fontSize: 13),),
],
),
),
Text('#' + data.id.toString(), style: TextStyle(color: Colors.black, fontSize: 13),),
],
),
Text(
data.title.toString(),
style: getSemiBoldStyle(color: Colors.black),
),
Text(
data.body.toString(),
style: getRegularStyle(color: Colors.grey).copyWith(fontSize: FontSize.s14),
maxLines: 3,
overflow: TextOverflow.fade,
),
],
),
),
),
This is where I want to show the Comments data of the post according to the post id provided
Consumer(
builder: (context, ref, child) {
final posts = ref.watch(commentProvider);
return ListView.builder(
itemCount: posts.length,
itemBuilder: (context, index) {
final data = posts[index];
return Container(
child: Column(
children: [
Container(
width: MediaQuery.of(context).size.width,
padding: EdgeInsets.all(AppPadding.p16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// Row(
// children: [
// Text(
// data.email.toString(),
// style: TextStyle(
// color: Colors.black, fontSize: 13),
// ),
// Text(
// '#' + data.id.toString(),
// style: TextStyle(
// color: Colors.black, fontSize: 13),
// ),
// ],
// ),
// Text(
// data.body.toString(),
// style: getSemiBoldStyle(color: Colors.black),
// ),
// Text(
// data.body.toString(),
// style: getRegularStyle(color: Colors.grey)
// .copyWith(fontSize: FontSize.s14),
// maxLines: 3,
// overflow: TextOverflow.fade,
// ),
],
),
),
I know how to pass the post Id from one screen to another but I got no idea how to show the comments according to the passed post id using a provider. For example: when I press on post with a post id with 3, I want to see the comments of the post id 3 in the next page. At the moment, I am just able to show the comments by providing static post id value.
If you didn't understand my problem then please feel free to ask. I'll kindly elaborate. Any state management solution can be provided but Flutter Riverpod would be much appreciated.
The API was taken from here:
Posts data : (https://jsonplaceholder.typicode.com/posts)
Comments data :(https://jsonplaceholder.typicode.com/posts/{post_id}/comments) or
Alternative (https://jsonplaceholder.typicode.com/comments?postId=1)
You can use the modifier .family
. For example:
final commentsProvider = FutureProvider.family<List<Comment>, int>((ref, postId) async {
final dio = Dio();
try {
final response = await dio.get(Api.commentApi, queryParameters: {
'postId': postId,
});
return (response.data as List).map((e) => Comment.fromJson(e)).toList();
} on DioError catch (err) {
print(err);
return [];
}
return [];
});
In widget:
Consumer(
builder: (context, ref, child) {
...
final comments = ref.watch(commentsProvider(postId));
...
}
)
You can read more here: family modifier