kanwar manraj
kanwar manraj

Reputation: 552

List view not getting rebuild properly

I have this comment section in my application.
User can like a comment. Whenever a comment is added, I call the database to get the latest comment and rebuild the class.
But as shown below When a new comment is added, it retains the state of the previous comment

demo

as seen above when a not liked comment is added it is having state of previous comment


Below is the given code
 @override
  void initState() {
    getComments();
   
    super.initState();
  }

  getComments() async {
    try {
      List<Comment> commentList =
          await Provider.of<Database>(context, listen: false)
              .postComments(widget.postid);

      setState(() {
        data = commentList;

        });
    } catch (e) {
      setState(() {
        data = 'error';
      });
      // throw ('e');
    }
  }

  dynamic data;


  addComment(BuildContext context) async {
    String commentData = _textEditingController.text.trim();
    if (commentData.isNotEmpty) {
      setState(() {
        showShimmer = true;

        _textEditingController.clear();
      });
      bool result = await Provider.of<Database>(context, listen: false)
          .addMessageToPost(widget.postid, true, commentData);

      if (result) {
        getComments();
      }
    }
  }

  final TextEditingController _textEditingController = TextEditingController();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: settingsAppBar(context, 'Comments'),
      body: Column(
        children: [
          showShimmer
              ? Shimmer.fromColors(
                  baseColor: Colors.grey[200]!,
                  highlightColor: Colors.grey[100]!,
                  child: ShimmerWidget())
              : Container(),
          Expanded(
            child: data == null
                ? Center(child: CircularProgressIndicator())
                : data == 'error'
                    ? Center(
                        child: Row(
                          mainAxisAlignment: MainAxisAlignment.center,
                          crossAxisAlignment: CrossAxisAlignment.center,
                          children: [
                            TextButton(
                                onPressed: () {
                                  getComments();
                                },
                                child: Text('Retry')),
                          ],
                        ),
                      )
                    : data.length >= 1
                        ? RefreshIndicator(
                              onRefresh: () async {
          setState(() {
            data = null;
          });
          getComments();
        },
                          child: ListView(
                              controller: _scrollController,
                              children: buidlCommentWidgets()),
                        )
                        : Text('No data'),
          ),
          SafeArea(...textfield)  ],
                  ),
                ),
              ],
            ),
          ),
        ],
      ),
    );
  }

  List<Widget> buidlCommentWidgets() {

    List<Widget> commentWidgetList = [];
    for (var i = 0; i < data.length; i++) {
      commentWidgetList.add(Padding(
        padding: const EdgeInsets.symmetric(vertical: 0.0, horizontal: 8.0),
        child: CommentListTile(
          comment: data[i],
          postUid: widget.postedUid,
        ),
      ));
    }
    return commentWidgetList;
  }
}

//////////////////////////////////////////////////////////////

class CommentListTile extends StatefulWidget {
  const CommentListTile({
    Key? key,
    required this.comment,
    required this.postUid,
    this.isReply = false,
  }) : super(key: key);

  final Comment comment;
  final String postUid;
  final bool isReply;

  @override
  _CommentListTileState createState() => _CommentListTileState();
}

class _CommentListTileState extends State<CommentListTile> {
  late bool isLiked;
  late int likeCount;

  handleLike(BuildContext context) async {
    setState(() {
      isLiked = !isLiked;
      likeCount = isLiked ? likeCount + 1 : likeCount - 1;
    });

    bool result = await Provider.of<Database>(context, listen: false)
        .postActivity(
            PostActivityEnum.likeDislikeComment, widget.comment.commentId);

    if (!result) {
      setState(() {
        isLiked = !isLiked;
        likeCount = isLiked ? likeCount + 1 : likeCount - 1;
      });
    }
  }

  @override
  void initState() {
    isLiked = widget.comment.isLikedByViewer;
    likeCount = widget.comment.likesCount;

    super.initState();
  }

  @override
  Widget build(BuildContext context) {
  
....ListTile


Upvotes: 0

Views: 79

Answers (1)

Kishan Dhankecha
Kishan Dhankecha

Reputation: 1005

This is a very common problem in the flutter.

This happens due to the widget tree and the render tree difference, Identification of the widget by its own Key can be easier for the flutter to keep an update on both render and widget tree.

For an easy solution, you can pass a unique key to the CommentListTile widget while building the list and also while adding a new widget to the list.

  List<Widget> buidlCommentWidgets() {
    List<Widget> commentWidgetList = [];
    for (var i = 0; i < data.length; i++) {
      commentWidgetList.add(Padding(
        padding: const EdgeInsets.symmetric(vertical: 0.0, horizontal: 8.0),
        child: CommentListTile(
          key: SOME_UNIQUE_KEY_HERE // Add Unique key here
          comment: data[i],
          postUid: widget.postedUid,
        ),
      ));
    }
    return commentWidgetList;
  }

It can be easy if you have some kind of commentId.

EDIT: 27 Aug 2021

You definitely should use your buildCommentWidgets() method like this:

  List<Widget> buidlCommentWidgets() {
    return data.map((comment) {
      return Padding(
        padding: const EdgeInsets.symmetric(horizontal: 8.0),
        child: CommentListTile(
          key: SOME_UNIQUE_KEY_HERE // Add Unique key here
          comment: comment,
          postUid: widget.postedUid,
        ),
      );
    }).toList();
  }

Upvotes: 1

Related Questions