The best way to avoid routing before certain async data in the Vuex store has finished loading

I am facing a challenge in my application where I require certain data to be loaded into the VueX store before routing can commence, such as user sessions.

An example scenario that showcases a race condition is as follows:

// Defined routes
{
  name: 'login',
  path: '/login',
  component: Login,
  meta: {
    goToIndexIf: () => store.getters['auth/loggedIn']
  }
}

In this case, the route guard may execute before the user information has been fetched from the server.

Even though I attempted conditional rendering, it did not solve the issue as the route guards function regardless of whether

<router-view v-if="storeReady">
is present in the rendered template or not.

Is there a way for me to ensure that all my routing operations wait for asynchronous data to be loaded?

Answer №1

Implementing a solution is straightforward. Simply include an init or similar Vuex action in the necessary sections of your store.
This should produce a Promise for all critical data requests that your application depends on:

init ({ dispatch }) {       // Alternatively, can be made async and utilize await instead of return
  return Promise.all([
    dispatch('getUserSession'), // Utilizing another <b>action</b>
    dispatch('auth/init'),      // From a different module
    fetch('tehKittenz')         // Utilizing the native <b>fetch</b> API
    // ...
  ])
}

The provided code can work with anything that returns a Promise.

Subsequently, establish a global navigation guard in your router using beforeEach.
This guard will hold off on navigating until the promise generated by a dispatch to the store resolves.

// Within your router initialization section
const storeInit = store.dispatch('init')

// Prior to <b>all other beforeEach</b>
router.beforeEach((to, from, next) => {
  storeInit.then(next)
    .catch(e => {
      // Manage any errors that arise
    })
})

This approach ensures that if routing occurs before the complete loading of the store, the router will patiently wait.
In the event that routing takes place afterwards, the promise will have already been fulfilled and routing will progress smoothly.

Remember to employ techniques like conditional rendering to prevent displaying an empty screen while routing awaits data retrieval.


*: By doing this, all routing and navigation activities are suspended during data retrieval processes. Exercise caution.

Answer №2

Ever since the initial inquiry, vue-router (v3.5.1) now offers a way to detect the first navigation, enabling actions like this to be executed exclusively on the initial route.

You can compare from with VueRouter.START_LOCATION.

import VueRouter from 'vue-router'

const router = new VueRouter({
  // ...
})

router.beforeEach((to, from, next) => {
  if (from === VueRouter.START_LOCATION) {
    // handle Vuex initialization/hydration during initial navigation.
    initializeOrWait().then((isLoggedIn) => {
      // adjust navigation or apply appropriate guard logic as needed.
      next();
    });
  } else {
    next();
  }
})

Answer №3

One successful approach I found was to encapsulate my Vue instance (new Vue({... })) within a .then() Promise. This promise would resolve(null) if everything goes smoothly, and it will resolve an error in case of any issues. This way, I can render the Vue instance conditionally based on the presence of an error.

Here, I invoke my asynchronous function and wait for it to load the store before initializing my app

My async function utilizes the token to fetch the required data

By following this method, the route guards that rely on the fetched store data can operate effectively

I hope this explanation is helpful, and please excuse any shortcomings in my English :)

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

directive unit testing unable to access isolatedScope as it is not recognized as a valid

Currently, I am in the process of conducting unit tests on a directive that was previously created. For my initial test, I simply want to verify a specific variable within the scope of the directive. However, whenever I attempt to execute the method isola ...

What could be causing the child of an ES6 imported object to return as undefined?

Here is the code snippet I am working with: import * as _routes from '../../routes' console.log('parent:', _routes) console.log('child:', _routes.breadcrumb) This code produces the following output: https://i.stack.imgur.co ...

Ways to extract innerHTML content from a loaded element generated by using the .load() method

Check out the code snippet below: template.html : <div id="nav"> Welcome to Space </div> layout.html : <div id="content"> </div> $('#content').load("template.html #nav"); ale ...

Tips for transferring state value from a form to a child modal

As a newcomer to React, I am uncertain about the best approach to take in my project. Specifically, I have a modal component that should appear once the user fills out a form and clicks on the Preview Voucher button to display the entered values. Below, yo ...

What is the best way to transfer the array from my function and have it returned?

I've been struggling to successfully pass my array to an external function. Can anyone help me with this? You can find the code that I'm working on in jsbin: https://jsbin.com/kugesozawi/edit?js,console,output. The expected result should be passe ...

Using Selenium WebDriver to Extract Variables from JavaScript SourceCode

Currently, I am dealing with a web page source code that utilizes JavaScript to display text. Below is an excerpt from the source: var display_session = get_cookie("LastMRH_Session"); if(null != display_session) { document.getElementById("sessionDIV") ...

NodeJS introduces the nullish coalescing assignment operator (??=) for effective nullish value handling

Is it possible to use the Nullish coalescing assignment operator (??=) in NodeJS? const setValue = (object, path, value) => { const indices = { first: 0, second: 1 }, keys = path.replace(new RegExp(Object.keys(indices).join('| ...

Is there a way to call a Vue function from an onclick event in JavaScript?

Creating a vue component and trying to call a function defined in Vue methods using the onClick attribute when modifying innerHTML is resulting in an error message stating "showModal is not defined". Here is the showModal function where I'm simply try ...

Best practices for organizing an array of objects in JavaScript

I have an array of objects with nested arrays inside, and I need to restructure it according to my API requirements. [{ containerId: 'c12', containerNumber: '4321dkjkfdj', goods: [{ w ...

Determine the percentage of clicks on an HTML5 canvas radial progress bar

Recently, I designed a circular progress bar displaying a specific percentage. However, I am facing a challenge in determining how to calculate the percentage when a user clicks on either the black or green part of the circle. Could you provide insight on ...

How to display currency input in Angular 2

Is there a way to dynamically format input as USD currency while typing? The input should have 2 decimal places and populate from right to left. For example, if I type 54.60 it should display as $0.05 -> $0.54 -> $5.46 -> $54.60. I found this PLUN ...

Saving data to a database using jQuery Ajax when multiple checkboxes are checked

Looking for a solution to store checkbox values into a database using jQuery Ajax to PHP. To see a live demo, click here. The image above illustrates that upon checking certain checkboxes and clicking Update, the checkbox values along with their IDs will ...

Tips for safeguarding AJAX or javascript-based web applications

Utilizing AJAX, this function retrieves information about an image in the database with the ID of 219 when a button is clicked. Any visitor to this webpage has the ability to alter the JavaScript code by inspecting the source code. By modifying the code a ...

Create a function that adds a new div element with a one-of-a-kind identification when

I am currently developing a web application on www.firstusadata.com/cash_flow_test/. The functionality involves two buttons that add products and vendors dynamically. However, the issue I'm facing is that the appended divs do not have unique IDs, maki ...

Is there a way to delete a table's row using JavaScript?

Hey there, total newbie to coding here. I'm working on a simple to do list project. The adding function is working great, and here's the code for it: let salvar = document.getElementById("salvar") let remove = document.getElementById("remove ...

Two-column layout with consistent height vertically, but varying heights on individual rows

By using JavaScript, I am able to ensure that two columns have equal height. The left column contains user input which can vary in length, causing some columns to have more content than others. My current issue is that there are multiple rows instead of ju ...

Difficulty arises when trying to extract specific information from an ajax response using the jQuery.filter

The code snippet below seems to be causing some trouble. It's supposed to filter HTML content that includes a div with the class "filtered_entries_box", but it's not working as expected. $.ajax({ "url" : "start.php", "type" : "POST", ...

When JSON contains slashes, JSON.parse will trigger an error

I am struggling with a valid JSON generated using PHP like this: var json = <?php echo json_encode(['somearray']); ?>. Inside the array, there is an HTML string as shown below: $myArray = ['image' => '<img src="/img/f ...

What is the best way to access a Python API or local data within the Google Visualization DataTable JavaScript library?

I have been tirelessly working for the past two weeks to figure out how to load a local CSV file into google.visualization.DataTable() or use Ajax to call a Python Flask API that I created. My ultimate goal is to dynamically create a Gantt chart. Here&apo ...

How can I integrate Apple remote support into a website with the use of Javascript?

One thing that I find interesting is the ability to use the Apple remote with Front Row, as well as other apps on Mac that support it. I'm curious about whether Web Apps could also be made compatible through Javascript. I have a concept for a TV-like ...