Search code examples
vue.jsvuexnuxt.js

Conditional state based on the route


I have a Vuex state property that stores a boolean that I use to determine whether to show or hide the nav bar. For all pages except the landing page the nav bar should appear so I set the default value to true.

export const state = () => ({
    showNav: true
})

Then I have a mutation for toggling that.

export const mutations = {
    toggleNav (state, show) {
        state.showNav = show
    }
}

In my landing page, I have a call to toggleNav to turn off the nav bar.

export default {
    mounted () {
        this.$store.commit('toggleNav', false)
    }
}

This works as expected with one big problem; When I refresh the landing page I see the nav bar for a brief second until mounted() gets called.

Is there some way to hide the nav bar such that it doesn't briefly appear? I realized I could default showNav to false and then call this.$store.commit('toggleNav', true) on every page but that seems unwieldy.

EDIT: The nav bar is itself its own component.

EDIT 2: I forgot to add that I need to be able to dynamically show the nav bar when scrollY exceeds a certain value and then hide it again when scrollY returns below that value. My apologies to everyone who answered for not being clearer about this.


Solution

  • In Nuxt, middlewares attached to a layout or a page are run on load and on every route change.

    So the most straightforward way is to use a middleware to check for current path and toggle your nav:

    /* store/index.js */
    export const store = () => ({
      showNav: true
    });
    
    export const mutations = {
      toggleNav(state, bool){
        state.showNav = bool;
      }
    }
    
    
    /* middleware/toggleNavMiddleware.js */
    export default function(context){
      const { route, store } = context;
      store.commit('toggleNav', route.path === /* your landing page path */);
    }
    
    
    /* layouts/default.vue (assuming this is the target) */
    /* you can also use it in pages/*.vue */
    export default {
      middleware: ['toggleNavMiddleware'],
    }
    
    
    /* components/NavBar.vue */
    <template>
      <nav v-if="$store.state.showNav">
        <!-- content here -->
      </nav>
    </template>