Vue js make nested component stay in parent when store updated

Viewed 88

I am creating a chat messaging system, where I populate the store with root messages and then map the state of that list (array). When posting a new message the store gets updated and the new post will be displayed, all OK. The issue is that the root message can have a reply thread so I nested another component and when the show replies button is pressed I populate an object with the list of replies and that also gets rendered fine, but if that thread is open and I post a new message above it removes the reply thread from the previous message.

The structure of my data is like this: (I will have an array of these)

rootMessages {
    id: 1234,
    body: 'some message text',
    etc...
    replyMessages: {
        replies: [
            replyMessage {
                id: 4567,
                body: 'some reply 1',
                replyTo: 1234
            },
            replyMessage {
                id: 4568,
                body: 'some reply 2',
                replyTo: 1234
            },
            etc...
        ]
    }
}

The main component will loop over the messages

<b-list-group>
    <root-message-component
    v-for="(m, index) in rootMessages"
    :message="m"
    ></root-message-component>
</b-list-group> 

The root message component will display the root info and then loop the replies

<template>
  <div>
    <b-list-group-item>
     <p>{{message.body}}</p> // etc..
    </b-list-group-item>
    <div class="reply-container">
    <b-list-group>
      <reply-message-component>
        v-for="(r, index) in message.replyMessages.replies"
        :reply="r"
      </reply-message-component>
    </b-list-group>
    </div>
  </div>
</template>

Then the ReplyMessageComponent will display the text in the body etc.

So if the reply thread is open, the html gets rendered and displays as expected, but when a new message is posted (unshift a new message to the root messages array in the store) the reply thread html gets replaced in the DOM with <!---->

The interesting thing is that if I delete that new root message then the reply thread reappears correctly again!. Its like the reply thread is stuck in that position in the DOM and does not get pushed down with the outer component.

1 Answers

Thank you Christopher Shroba, your comment about using keys with the link for maintaining state, that really helped. I was using keys for my loops but I was using the index like so

v-for="(m, index) in rootMessages" :key="index"

and the same in my replyMessages

what I had to do was give unique keys across both arrays so I ended up using the message/reply id's which I know are unique, like so

v-for="(m) in rootMessages" :key="m.id"

and

v-for="(r) in replyMessages" :key="r.id"

Now this gives me the expected behaviour.

Related