1

I'm trying to check each comment and comment reply made by the user and check if they made the comment more than 30 mins ago then they can't edit it, however the way I'm doing it isn't working and I'm getting this error

[Vue warn]: You may have an infinite update loop in a component render function.

This is the code in question

<div v-for="comment in forum.comments">
    <el-card shadow="never">

    //check for other things 
    //set the comment info and layout

        <div style="text-align: end" v-if="comment.user_id === $page.auth.user.auth.user.id">
            {{minutes(comment)}}
            <div v-if="editRemove === false" class="btn-link-edit action-button"
                @click="edit(comment)">
                <i class="fas fa-pencil-alt"></i>
            </div>
        </div>

        <div v-for="reply in comment.replies">

        //check for other things 
        //set the reply info and layout

            <div style="text-align: end" v-if="reply.user_id === $page.auth.user.auth.user.id">
                {{minutes(reply)}}
                <div v-if="editRemove === false" class="btn-link-edit action-button"
                    @click="edit(reply)">
                    <i class="fas fa-pencil-alt"></i>
                </div>
            </div>
        </div>
    </el-card>
</div>

data return

editRemove: false,

method

minutes(item) {
    var minutes = moment().diff(moment(item.comment_time), 'minutes');
    if (minutes >= 30) {
        this.editRemove = true;
    } else if (minutes <= 29) {
        this.editRemove = false;
    }
}

What should I do to fix this?

6
  • As you have 2 if's and no default case perhaps this is the reason, the compiler complains. Try to change } else if (minutes <= 29) { to } else {. ALso you can write it much shorter with this.editRemove=minutes >= 30 Commented Jan 21, 2020 at 17:23
  • @thopaw I changed it and it made no difference Commented Jan 21, 2020 at 17:25
  • you have two v-for, you have a function in template v-for iterations, i.e minutes(comment), you are editing the same variable editRemove in that function. So you are constantly changing that same variable value. Commented Jan 21, 2020 at 17:29
  • @AJT82 since I'm trying to make this as dynamic and for an unknown amount of comments how would I fix that? Commented Jan 21, 2020 at 17:40
  • 1
    I would make dumb components (child components) for comments and replies, you could use computed property for calculating your minutes. Anyway, even though you wouldn't face this infinite loop issue, it would never work with just one variable editRemove, all comments and replies need to have an unique identifier. Commented Jan 21, 2020 at 17:43

1 Answer 1

1

As I mentioned in comment, you are constantly changing the one and the same variable this.editRemove so change detection is happening and causes therefore something similar to an infinite loop. As also mentioned, I would make child component(s) for comments and replies. Though I said you can use a computed property, that won't work when thinking about it a second time ;) since it's not reactive. So I'd use an interval in the child component to check once a minute the amt of minutes that have passed since comment/reply has been posted.

So I would create a child, let's say Comment, pass the current comment in the v-for to the child:

<div v-for="comment in forum.comments">
  <Comment :comment="comment"/>
</div>

Then the child would have the button and checks the time and whether to display edit button or not:

<button v-if="isEdit" @click="editComment">Edit</button>

isEdit is determined on component creation, and after that, every 60 seconds. When destroying component, remember to clear the interval.

Child:

props: {
  comment: Object
},
data() {
  return {
    isEdit: Boolean,
    interval: null
  };
},
methods: {
  editComment() {
    console.log(this.comment)
    // do your magic
  },
  checkTime() {
    var minutes = moment().diff(moment(this.comment.comment_time), "minutes");
    if (minutes >= 30) {
      this.isEdit = true;
      // here you could also already clear the interval, since it won't change
    } else if (minutes <= 29) {
      this.isEdit = false;
    }
  }
},
created() {
  this.checkTime();
  this.interval = setInterval(() => {
    this.checkTime();
  }, 60000);
},
beforeDestroy() {
  clearInterval(this.interval);
}

This demo is just for comments, but the same would be for replies.

CODESANDBOX, for the demo I made some changes to the interval and changed minutes to seconds. So after 10 seconds the 2 other buttons should appear.

Sign up to request clarification or add additional context in comments.

8 Comments

ok I have a question, for the replies do I create another component and call it in the same way as you do here, just with the reply component? ``` <div v-for="comment in forum.comments"> <Comment :comment="comment"/> </div> ```
also, I have edit and delete funtionality with the comments and replies, do I move those to the component file ?
is your comment and reply exactly the same and same props? I would have thought that they are different. But if not. Then I would perhaps make a further child component, which just displays text and calculates the time. The Comment component would be wrapped around it and you can v-for replies to each comment in the Comment component and just use the child in both. And yes, I would move the edit and delete to the component(s). Of course you could communicate those to the parent to handle. It's up to you.
they are almost the same, but have layout differences, one less button and cannot be replied to. I also want to send another object as well as the comment because I use it in the comment layout, how can I do that?
just add a new prop to the tag.. whatever you need it to be: <Comment :comment="comment" :someobject="myobject"/>. Pseudo code. Register the the object you pass to the props section in Comment component.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.