What is the best practice for preloading route data before navigating to the route?

When preparing to render a page for a specific route, my goal is to fetch the necessary data synchronously first. Ideally, I prefer to handle the data fetching within the page component, but I am open to doing it in the router files as well. I have experimented with different methods, but the challenge lies in the various ways components can be built and the differences in feature usage.

In my scenario, I am creating single file components using the Composition API and <script setup> syntax. The Vue Router documentation discusses "fetching before navigation" where options like beforeRouteEnter or beforeRouteUpdate are mentioned, but these are demonstrated using the Options API. Although there is a section for the Composition API which talks about utilizing onBeforeRouteUpdate within the setup() function, experimentation has led me to try out using <script setup>:

<script setup>
import { onBeforeRouteUpdate } from 'vue-router'

onBeforeRouteUpdate(() => {
  console.log('onBeforeRouteUpdate')
})
</script>

Unfortunately, this approach does not work as expected. A method that has shown some success is fetching the data in the router using the beforeEnter guard and then setting the data onto the meta property, which can be accessed on the route instance in the component:

beforeEnter: (to, from, next) => {
  fetch('https://pokeapi.co/api/v2/pokemon/ditto')
    .then(res => res.json())
    .then(res => {
    to.meta.pokemon = res;

    next();
  });
}

It's worth noting, however, that as indicated in the documentation, beforeEnter only triggers when entering the route. Changes in parameters will not trigger this again, requiring the setup of a watcher on the route in the component itself. At this point, it may have been simpler to include all this logic within the component directly.

Despite my efforts, I still haven't found an ideal solution for this process, but I'm open to suggestions and guidance. Any pointers or advice would be greatly appreciated. Thank you in advance.

Answer №1

If you're looking for a solution, consider using top level await with Vue. Check out this link: https://vuejs.org/api/sfc-script-setup.html#top-level-await

To implement this approach, simply wrap your RouterView component in a Suspense component like demonstrated here: https://vuejs.org/guide/built-ins/suspense.html#combining-with-other-components (make sure to exclude unnecessary components).

Keep in mind that the 'loading screen' will be visible during the initial request.

If you'd like to test it out, I've created a demo for you to explore: https://github.com/ileue/vue-top-level-await-demo

Answer №2

Initially, it's important to note that beforeRouteUpdate is specifically triggered when updating the current route, not when transitioning to another component or page as clarified here.

An instance where this lifecycle hook could be activated is shown below:

<button @click="$router.push({ hash: `#${Math.floor(Math.random() * 10)}` })">
  random hash
</button>

onBeforeRouteLeave functions smoothly when transitioning between pages.

In response to the initial inquiry, one approach is to incorporate a form of router middleware similar to how Nuxt handles it. This enables you to await an HTTP call and permit navigation only after it has been completed, thereby establishing a blockade effect during navigation.

Although I am unaware of how to implement this using the Composition API, it is known to function effectively with the Options API (numerous blog posts are available on this topic). Given that setup operates within its own lifecycle, certain aspects may pose challenges.

In summary, combining a traditional router middleware with a wrapper around your pages (like a layout) seems ideal in this scenario. This allows for a single watcher to monitor multiple pages simultaneously.

The effectiveness of these strategies largely depends on the organization and structure preferences of individual developers.


Skeleton screens impart a perception of swiftness compared to obstructive loading screens. Alternatively, utilizing prefetching (commonly included in Nuxt by default) can provide insights and potentially preload necessary assets before they are required. Various techniques in this realm can expedite network requests and enhance performance overall.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

I am experiencing an issue where the Mongo item ID is not being successfully passed through the REST API

Recently, I've been working on developing a blog site for my class project. The main goal is to create a REST API for the blog site. I have successfully managed to display data from the database using .ejs views, except for one issue. I am facing diff ...

What is the best way to implement JavaScript for loading and removing content based on button clicks on a webpage?

I'm in need of a vanilla JavaScript solution (I know JQuery options exist, but I want to stick to vanilla JS for now)? Currently, I am using a simple page as a testing ground for my ongoing project. The page consists of two buttons that load HTML pag ...

I am struggling with clicking on Bootstrap's pagination using AngularJS

I'm still getting the hang of Angularjs. I managed to set up a pagination system, but for some reason, I can't seem to interact with it when I run my project. Take a look at this screenshot that illustrates my issue: https://drive.google.com/fil ...

Issue encountered while attempting to save a value in localStorage

I am encountering an issue while trying to save and read the value of a button in the panel. The error message I receive is - Unable to set property 'adl' of undefined or null reference. This is my first time working with localStorage, so I' ...

Is there a way to retrieve two distinct data types from a single ng-model within a select option?

My mean stack code is functioning well, but I am looking to enhance it by adding a new feature. Specifically, I want to retrieve more elements from my NoSql database while selecting options. This is the structure of my database: Tir2 :id, price, xin, yin ...

Troubleshooting the net::ERR_ABORTED 404 (Not Found) error while utilizing next/link to call an API route in NextJS

While developing an api route for downloading a CSV file, I encountered an error when using Next Link. Unfortunately, switching to another method is not an option as it would cause my application to fail to build. The component in question is straightforwa ...

Utilize Google Maps to receive directions to a specific destination and discover current traffic conditions along the route using their comprehensive API

I am currently working on implementing the Google Maps direction identifier functionality with traffic details. However, I am able to obtain directions but not specific traffic details for a selected path; it seems to apply overall traffic data instead. ...

Utilizing ControlValueAccessor in various components

I am currently working on a component that implements the ControlValueAccessor interface, and I am facing some difficulties in understanding how to properly utilize it: // Angular Imports import { Component, OnInit, forwardRef, Output, EventEmitter, OnC ...

Tracking the progress bar as files are being uploaded via AJAX using HTML5

Currently, I have a progress bar that increments based on the number of files and their sizes. I am looking to implement an overall progress bar to display while uploading files to the server using AJAX and HTML5. Each file is uploaded individually to th ...

A method to verify the presence of a specific element within a list using JavaScript

I'm trying to validate if the list retrieved from the application contains the expected element. Can you please review my code and let me know where I might be making a mistake? this.verifyOptionsInDropdown = async function(){ var optionList = a ...

The state may be modified, but the component remains unchanged

I've been tasked with implementing a feature on a specific website. The website has a function for asynchronously retrieving data (tickets), and I need to add a sorting option. The sorting process occurs on the server side, and when a user clicks a s ...

What materials are required in order to receive messages and information through my Contact page?

Currently, I am pondering the optimal method for gathering information from my Contact page. I have already created a form; however, I'm unsure how to send the gathered data to myself since I am relatively new to Web development. Angular is the framew ...

When it comes to successful payments, should you use `checkout.session.async_payment_succeeded` or `checkout.session.completed` in the Stripe event?

I'm feeling a little uncertain about the differences between two events: checkout.session.async_payment_succeeded & checkout.session.completed Currently, I am utilizing checkout.session.completed, but I'm wondering if checkout.session.async ...

Analyzing DynamoDB Query

I am on a mission to recursively analyze a DynamoDB request made using the dynamo.getItem method. However, it seems that I am unable to locate a similar method in the DynamoDB SDK for Node.js. You can find more information about DynamoDB SDK at http://do ...

What is the purpose of storing the Vue instance in a variable or constant?

As a newcomer to Vue, I've noticed that in many tutorials and documentation sources, the new Vue instance is often stored in a variable like app. I'm curious, what is the benefit of saving the Vue instance in a constant or variable? const app = ...

Retrieve the radio button value from the HTML form

This website is designed to calculate ideal weight based on input data, but I am encountering an issue with the gender selection. The code seems to only recognize the first condition for female, while ignoring the else if condition for male. How can I fix ...

Utilizing Conditional Logic to Create a Dynamic Menu

I have a navigation menu on my website that is divided into two sections. There is a left panel and a right panel which slide in from the side when their respective buttons are clicked, covering the browser window. The functionality of sliding in the pan ...

Steps for passing a layout property to a page component in Nuxt.js

I'm new to VueJS and NuxtJS, and I'm having trouble passing a property from a layout to a page component. Below is my layouts/default.vue <template> <Nuxt myprop="hello world" /> </template> <script> export ...

"Is there a way to modify the color of the button once it's been clicked, but only for the specific button that was

Looking to create a Quiz App using React and facing an issue where all buttons change color when clicked, instead of just the one that was clicked. Any solutions on how to make only the clicked button change its color in React.js? App.js import Main from ...

Transition one background image into another using background positioning

Snippet of code: https://jsfiddle.net/foy4m43j/ HTML: <div id="background"></div> CSS: #background { background-image: url("http://i.imgur.com/hH9IWA0.png"); background-position: 0 0; background-repeat: repea ...