0

I have a some middleware in my Nuxt app that closes a fullscreen mobile menu when a new route is clicked. What I am experiencing is the following:

  1. user clicks nuxt-link
  2. menu closes
  3. asyncData delay (still shows current page)
  4. new page is loaded upon resolved asyncData

What I would like is the following:

  1. user clicks nuxt-link
  2. asyncData delay (if exists)
  3. menu closes upon new page load

Is it possible to have an asyncData watcher in Nuxt middleware?

I know I can hack this by creating a store value that tracks asyncData load, but I'd rather not have to wire up such a messy solution to each and every page that uses asyncData.

Note - not every page uses asyncData.

2 Answers 2

3

I think that the best option would be to leave the menu open, and then when the new page finishes loading (probably on the mounted hook) send an event or action to close the menu.

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

2 Comments

After sleeping on this, I think this is the best path forward as well. Thank you!
I came up with a somewhat elegant (IMO) solution below. Feel free to give your thoughts.
2

I figured this out in a more elegant solution than having to implement a store.dispatch function on each individual asyncData function.

So what I did was use a custom loading component: https://nuxtjs.org/api/configuration-loading/#using-a-custom-loading-component

However, instead of showing a progress bar or any sort of loading animation, I just used this component to set a loading state in my vuex store. Note - it forces you to have a template, but I just permanently disabled it.

<template>
  <div v-if="false"></div>
</template>

<script>
  export default {
    methods: {
      start() {
        this.$store.dispatch('updateLoadingStatus', true);
      },
      finish() {
        this.$store.dispatch('updateLoadingStatus', false);
      }
    }
  };
</script> 

Then in my middleware, I set up an interval watcher to check when loading has stopped. When stopped, I stop the interval and close the mobile menu.

export default function({ store }) {

  if (store.state.page.mobileNav) {
    if (store.state.page.loading) {

      var watcher = setInterval(() => {
        if (!store.state.page.loading) {
          store.dispatch('updateMobileNav', false);
          clearInterval(watcher);
        }
      }, 100);

    } else {
      store.dispatch('updateMobileNav', false);
    }
  }
}

This doesn't specifically have to be for a mobile menu open/close. It can be used for anything in middleware that needs to wait for asyncData to resolve. Hope this can help anyone in the future!

4 Comments

In this case instead of intervals you can have a vue watcher waiting for the store to change
@EderChrono I wasn't aware that I could implement a vue watcher inside Nuxt middleware? Can you give an example of how to do so?
You're right that's not possible, I thought that the interval was inside a component.
IMHO, any solution using setInterval isn't really "elegant" =).

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.