vue.jsvuejs3nuxt.jsnuxt3.js

Caching - watch, refs, and navigation behvior


I'm having this issue where I'm using Vue3 and Nuxt, and I need a loading function to run once everytime the user navigates to the page, but delay loading if the global data isn't available yet.

const depositsLoading = ref(true);
const fetchDeposits = async () => {
  //... Load locally dependent data
};


const stopCompaniesWatch = watch(
  () => companies.selected, // check to see if the global data that loads on app load is available
  (loaded) => {
    console.log('WATCHER RUNNING: ', loaded)
    if (loaded || companies.selected) { 
      console.log('LOADED TRUE')
      fetchDeposits();
      stopCompaniesWatch();
    }
  }
)

This code works as expected on page refresh, but not on page navigate away and navigate back (nav back). On nav back, the depositsLoading is set to true and the page is stuck in the loading state forever. Here's what I've learned happens on nav back:

So its like some of the setup tag reruns on nav back but not all of it?

My quesitons:

  1. Why is this happening?
  2. How do I make my page refecth locally dependent data on nav back?

MRE - no idea how to provide one as this question depends on navigation, so at the least it requires a whole nuxt server. If someone knows how I could provide this let me know.


Solution

  • setup tag reruns

    Of course setup will be reruned when you navigate back if this component is not keep alived

    the watch callback is supposed to be run once on page load

    The watch callback is not supposed to be run once on page load. It runs when you refresh the page because companies.selected changes from false to true. But when you navigate back, companies.selected is always true and won't trigger the watch callback. If you still want the callback to run, pass the immediate: true option. Ref: https://vuejs.org/guide/essentials/watchers.html#eager-watchers

    Bonus

    I would recommend https://vueuse.org/shared/until/#until if you are using Vueuse. Example:

    ;(async () => {
      await until(() => companies.selected).toBe(true)
      fetchDeposits();
    })()