0

I'm trying to build a component that stays at the bottom of my pages to be a kind of log/status tool. The data are stored in a state in a store.js from the main App.vue. From the time being I just store when I click a button in another view.

When I try to do it on the App.vue for testing I encounter a problem:

<footer id="footer_id" class="container-fluid overflow-auto flex-shrink-0 flex-grow-0">
 <template v-for="line in storeState.loglines" >
   {{line}} <br v-bind:key="line" />
 </template>
</footer>

I need to add a <br/> to write it on a new line but vue asks me to bind it like I did, even if it's not really needed. The result is a warning when I press the button twice:

[Vue warn]: Duplicate keys detected: 'log-text'. This may cause an update error.

Where "log-text" is what I wrote in the log.

The store.js is very simple:

export const store = {
    state: {
        loglines: ['test1','test2'],
    },
    writeLog(line) {
        this.state.loglines.push(line);
        //scroll to bottom: don't know how to do it directly in the footer
        var objDiv = document.getElementById("footer_id");
        objDiv.scrollTop = objDiv.scrollHeight;
    }
};

How do I avoid the warning? Am I doing it wrong? As an alternative I might have to add a datetime as key on my store for each line of statuslog.

sebasaenz
  • 1,917
  • 2
  • 20
  • 25
maugch
  • 1,276
  • 3
  • 22
  • 46

1 Answers1

1

The key prop should be unique, so you could either use a datetime variable as you mentioned or simply add an index to the v-for directive and use it inside the template.

<footer id="footer_id" class="container-fluid overflow-auto flex-shrink-0 flex-grow-0">
 <template v-for="(line, i) in storeState.loglines" >
   {{line}} <br v-bind:key="i" />
 </template>
</footer>

EDIT: this is a solution for the problem that the OP presented.

As a personal choice and a general good practice I would rather solve the issue by putting the {{line}} inside a div and styling it accordingly.

Also I would perhaps choose not to use a template when using a div seems more appropriate.

Anyways, I limited myself to solving the issue regarding the repetition of the key value as that is the problem presented by the OP.

sebasaenz
  • 1,917
  • 2
  • 20
  • 25
  • 1
    Thanks for your soultion and idea! As it's basically a "tail" simulator, I thought having 100s of div in the DOM was a bad idea, that's why I tried with a template. I might investigate more if there are performance issues and if someone has already done a similar component. I can also delete lines from the log once it's too big. – maugch Sep 07 '20 at 07:19