2

I'm storing nav items in my Vuex store and iterating over them for conditional output, in the form of a Vue/Bulma component, as follows:

<b-navbar-item
  v-for='(obj, token) in $store.state.nav'
  v-if='privatePage'
  class=nav-link
  tag=NuxtLink
  :to=token
  :key=token
>
  {{obj.text}}
</b-navbar-item>

As shown, it should be output only if the component's privatePage data item resolves to true, which it does:

export default {
  data: ctx => ({
    privatePage: ctx.$store.state.privateRoutes.includes(ctx.$route.name)
  })
}

The problem I have is when I run the dev server (with ssr: false) the component doesn't show up initially when I navigate to the page via a NuxtLink tag. If I navigate to the page manually, or refresh it, the component shows.

I've seen this before in Nuxt and am not sure what causes it. Does anyone know?

kissu
  • 40,416
  • 14
  • 65
  • 133
Mitya
  • 33,629
  • 9
  • 60
  • 107
  • 1
    First off, you should not use `v-if` and `v-for` at the same time as told in the documentation. Same goes for data, please use a `return` there. Check if you have any error in your console or errors from ESlint. You can inspect your page with Vue devtools to see what is the issue (Vuex, local state or alike). Don't forget to use double quotes for all your props/attributes and please do not use the index of the `v-for` (named `token`) in your case. Maybe provide us some [repro] for a faster debug! – kissu Dec 18 '21 at 22:05
  • Thanks @kissue. My `data` does have an implicit `return` - it's just I'm using arrow function syntax. What's the reason to not use `index` for the key, out of interest? – Mitya Dec 19 '21 at 20:16
  • You're loosing the ability to use `this` to set some data. Also, `return` is important to not have a shared state across components. As for the `index` in `v-for`, here is [an article](https://michaelnthiessen.com/understanding-the-key-attribute) on why this is doing the opposite of what it's supposed to do. – kissu Dec 20 '21 at 00:17
  • Thanks. But I'm still confused about return - I AM using a return, just an implicit one, in the form of an arrow function. That is, `ctx => ({...})` is the same as `ctx => { return {...}; }` – Mitya Dec 20 '21 at 11:18
  • As told above, you're loosing the ability to use `this` (since it's one of the key points of an arrow function). Otherwise, it could work just as good (never tried to see if an implicit return prevents shared state), I just like to keep conventions here. Also, if you're using [Vue snippets](https://marketplace.visualstudio.com/items?itemName=sdras.vue-vscode-snippets), you don't really waste time writing it anyway. – kissu Dec 20 '21 at 11:20
  • 1
    Sorry, I had misunderstood you. You're quite right. Thanks. – Mitya Dec 20 '21 at 11:37

2 Answers2

1

recommendation :

  1. use mapState and other vuex mapping helper to have more readable code :).

  2. dont use v-for and v-if at the same element

  3. use "nuxt-link" for your tag

  4. use / for to (if your addresses dont have trailing slash)

<template v-if='privatePage'>
  <b-navbar-item
    v-for='(obj, token) in nav'
    class=nav-link
    tag="nuxt-link"
    :to="token"  Or "`/${token}`"
    :key="token"
  >
    {{obj.text}}
  </b-navbar-item>
</template>

and in your script :

<script>
import {mapState} from 'vuex'

export default{
   data(){
    return {
      privatePage: false
    }
   },
   computed:{
     ...mapState(['privateRoutes','nav'])
   },
   mounted(){
       // it's better to use name as a query or params to the $route
     this.privatePage = this.privateRoutes.includes(this.$route.name)
   }
}

</script>

and finally if it couldn't have help you , I suggest to inspect your page via dev tools and see what is the rendered component in html. it should be an <a> tag with href property. In addition, I think you can add the link address (that work with refresh and not by nuxt link) to your question, because maybe the created href is not true in navbar-item.

NOTE: token is index of nav array . so your url with be for example yourSite.com/1.so it's what you want?

kissu
  • 40,416
  • 14
  • 65
  • 133
sha
  • 147
  • 2
  • 16
  • Probably not. IMO. – kissu Dec 19 '21 at 09:40
  • Actually it is - my nav object in state takes the form of URI => link data, so `token` for the `to` prop is correct. Thanks for the other tips - I'll try them. – Mitya Dec 19 '21 at 20:18
0

This question has been answered here: https://stackoverflow.com/a/72500720/12747502

In addition, the solution to my problem was a commented part of my HTML that was outside the wrapper div.

Example:

<template>
  <!-- <div>THIS CREATES THE PROBLEM</div> -->
  <div id='wrapper'> main content here </div>
</template>

Correct way:

<template>
  <div id='wrapper'>
    <!-- <div>THIS CREATES THE PROBLEM</div> -->
    main content here
  </div>
</template>
Tronki
  • 1