Trigger API request only upon entrance of a specific Vue Router child route

Is there a way to trigger a store action in Vue2 and vue router 3x whenever a specific child route is accessed, regardless of whether it is through a button click or the browser back/forward buttons?

I have the need to make an API call every time a particular child route is visited. While my current code functions properly when navigating through buttons, it breaks when users use the browser's navigation buttons.

Let me explain the issue...

The structure of my router is as follows:

const router = new Router({
  mode: 'history',
  routes: [
    {
      path: '/browse/food/:foodId',
      name: 'Food',
      component: foodComp,
      children: [
        {
          path: ':routeTitle',
          name: 'FoodDescription',
          component: foodDescriptionComp,
          props: {
            viewMode: 'TEXT',
          },
        },
        {
          path: ':routeTitle',
          name: 'FoodImage',
          component: foodDescriptionComp,
          props: {
            viewMode: 'IMAGE',
          },
        },
        {
          path: ':routeTitle/food-translation',
          name: 'FoodTranslation',
          component: foodTranslationComp,
        },
      ],
    },
    ...lotsOfOtherRoutes,
  ],
});

...the foodDescriptionComp includes pagination for switching between different foods triggered by clicking the "next page" (or page number) button. The method for this functionality is defined as follows:

methods: {
  async switchPage(pageNumber, foodIdForPageSelection) {
    this.$router.push({
      name: 'FoodDescription',
      params: { foodId: foodIdForPageSelection },
    });

    await this.loadFoodByPage({
      catalogId: this.catalogId,
      pageNumber,
    });
  }
}

When a user uses the browser's back button, the loadFoodByPage method is not triggered. I've attempted several solutions:

One approach was to use the beforeEnter function and move the loadFoodByPage logic there, but it only fires on the initial page load.

Another potential solution could involve using beforeEach, but with hundreds of routes in our application, it seems excessive to add logic specifically for one child route that would be checked on every single page.

Although I tried a workaround involving the following hacky solution, it results in maintaining only one step in the history when pressing the back button - meaning if I navigate from login to food 1, then proceed to 2, 3, 4, and press back in the browser, it will go back to page 3 before redirecting to the login page. Even if this method worked, it goes against best practices.

// Reload page on browser back/forward button press
window.onpopstate = function () {
  window.location.reload();
};

Answer №1

This code should work in theory, although it has not been tested. The concept is that this function will be activated every time there is a route change, and the page number will be determined by the URL. If no page number is found in the URL, it defaults to 1.

methods: {
  switchPage(pageNumber, foodIdForPageSelection) {
    this.$router.push({
      name: 'FoodDescription',
      params: { foodId: foodIdForPageSelection },
      query: { pageNumber }
    })
},
watch:{
  '$route' (to, from){
    if(to.name === 'FoodDescription') {
      this.loadFoodByPage({
        catalogId: this.catalogId,
        pageNumber: this.pageNumber ? this.pageNumber : 1,
    });
    }
  }
},
computed: {
  pageNumber: () => {
      return this.$route.query.pageNumber;
    }
  }
}

Answer №2

I've experimented with a few strategies to tackle this issue:

Initially, I attempted incorporating beforeEnter and relocating loadFoodByPage to the beforeEnter, but it only triggered during the initial page load.

Using beforeEach seems like a potential solution, but considering the extensive number of routes in our application, it appears impractical to add logic specifically for one child route that would be evaluated on every single page.

Indeed, you have the option to utilize either beforeEnter or beforeEach to address this issue.

beforeEnter - as previously attempted, this method showed limitations by only functioning on the initial page load. The reason being that when returning to a route using the browser's back button, the beforeEnter is not re-evaluated.

beforeEach - this executes before entering each route, including when navigating back with the browser's back button. However, concerns about the performance impacts of adding this guard to all routes remain.

A possible resolution could involve implementing a dynamic module for your route. This approach allows you to apply the beforeEnter solely to the required routes without necessitating its inclusion in every route.

For example;

// Dynamic route module
const foodDescriptionModule = {
 beforeEnter: async (to, from, next) => {
   // Implement API call here
   await store.dispatch('loadFoodByPage', {
     catalogId: to.params.catalogId,
     pageNumber: to.params.pageNumber,
   });

   next();
 },
 children: [
   {
     path: ':routeTitle',
     name: 'FoodDescription',
     component: foodDescriptionComp,
     props: {
       viewMode: 'TEXT',
     },
   },
   {
     path: ':routeTitle',
     name: 'FoodImage',
     component: foodDescriptionComp,
     props: {
       viewMode: 'IMAGE',
     },
   },
   {
     path: ':routeTitle/food-translation',
     name: 'FoodTranslation',
     component: foodTranslationComp,
   },
 ],
};

// Main router configuration
const router = new Router({
 mode: 'history',
 routes: [
   {
     path: '/browse/food/:foodId',
     name: 'Food',
     component: foodComp,
     children: [foodDescriptionModule],
   },
   ...lotsOfOtherRoutes,
 ],
});

In this setup, the beforeEnter guard is defined within a separate module (foodDescriptionModule) and subsequently included in the children array of the primary route arrangement. Therefore, the beforeEnter guard exclusively applies to the routes specified in foodDescriptionModule, rather than affecting all routes across your application.

Note that this assumes the existence of the loadFoodByPage action in your vuex store. If not, adjustments will be necessary. Ensure to import the vuex store at the beginning of your file with import store from './store'. By following this approach, you should be able to execute a store action whenever a particular child route is accessed, regardless of whether it was reached through user interaction or browser navigation buttons.

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

Discovering Ways to Utilize User Controls with JavaScript

How do I manipulate my user control using JavaScript? <body> <form id="form1" runat="server"> <div> <uc1:WebUserControl ID="WebUserControl1" runat="server" Enabled="False" /> <input id="Button1" type="b ...

What is the best way to send props to FlatList using renderScene within react-native-tab-view?

As a newcomer to React Native, I am attempting to pass props to ListHeaderComponent within the FlatList. Below is the code snippet: const FirstRoute = (props) => { const _renderHeader = () => { return( <View> {props.isFoll ...

What are the reasons for the POST method malfunctioning in a mobile web application?

Currently, I am in the process of developing a mobile web application using PhoneGap. At the moment, I am successfully passing data between the client (HTML page on the mobile device) and the server (PHP on the server) using the GET method. However, when a ...

Retrieve the currency code based on the user's timezone

I need help finding a way to retrieve the local currency code of a user based on their timezone. As part of my workflow using Stripe and Firebase, I am creating a Firestore record when a user signs up. A function stores the user's timezone in the dat ...

Converting data from Random.org into an integer using JavaScript

I have been working on a small web application to experiment with CSS animations. Although it's functioning, I'm seeking more genuine randomness. To achieve this, I am exploring the use of Random.org. How can I import the output from Random.org i ...

Encountering NaN in the DOM while attempting to interpolate values from an array using ngFor

I am working with Angular 2 and TypeScript, but I am encountering NaN in the option tag. In my app.component.ts file: export class AppComponent { rooms = { type: [ 'Study room', 'Hall', 'Sports hall', ...

What is the method to conceal an element after detecting and locating a specific class using jQuery?

Can someone please assist me today with the following task: Step 1: <div id="htmlData"> <div class="col-md-12"> <div class="pull-left"> <h3>Report: <strong>Travel </strong></h3> ...

Paste a URL into the input field to view it on the current page

As someone new to HTML, I am in search of a code snippet that will allow users to input a URL in a text box and then be redirected to that URL after clicking on a button. The ideal solution for me would be a straightforward HTML code. I attempted using t ...

Tips for displaying Facebook comments with JavaScript

Can anyone help me figure out how to customize the data-href for Facebook comments using JavaScript (jQuery)? I tried incorporating the code below, but it's not displaying anything in the div col2. $("#col2").html( id+"<div class='fb-comm ...

Failure of $.post to activate the function

I'm really struggling to understand why the alert or console.log functions are not being triggered in this snippet of code: $.post("http://localhost:8080/mail", jsonObject, function(data) { ...

Angular detects when a user scrolls on a webpage

I have developed a straightforward navigation system using Angular. The main controller is responsible for generating the menu. <nav class="{{active}}" ng-click= ""> <a href="#a" class="home" ng-click= "active='home'">Home< ...

Is there a way to deactivate the <script> tag using CSS specifically for media queries?

When designing a website exclusively for desktop usage, I encountered the issue of it not being viewable on mobile devices. I attempted to address this problem by utilizing the code below: script { display: none; pointer-events: none; } Unfortunat ...

I am not encountering any errors; however, upon entering the room, my bot fails to initiate creation of a new channel

const Discord = require("discord.js") const TOKEN = "I forgot to include my token here" const { Client, GatewayIntentBits } = require('discord.js'); const { MemberFetchNonceLength } = require("discord.js/src/errors/Erro ...

Showing AngularJS information on Views

After successfully implementing static HTML with views, as shown in this example: https://embed.plnkr.co/MJYSP01mz5hMZHlNo2HC/ I am now facing a challenge with integrating the angular-ui accordion within ng-view. You can view the accordion I am attemptin ...

Switching URLs or internal pages using jQuery Mobile's select menu feature

Utilizing a select box as the navigation menu for my jQuery Mobile website. Some menu items link to internal pages while others link to external URLs. This is the code I'm using to change the page URL: $('#menu-select').change(function() ...

What is the best way to ensure that this form field remains hidden when the page is loaded?

In my Django project, I have a form that should only display the entity name on page load. However, it is currently showing both the entity name and quote text fields. The quote text field should only be visible when the entity name is not in the database. ...

Adding elements to an array appears to cause the previously created object to react

I am encountering a situation where once I add an object to an array, it becomes reactive to any changes made. // actions.js export const addToCart = ({ commit }) => { commit('addToCart'); // successfully updates the state setTimeout ...

Simple method for extracting data from JSON and saving it into an array with jQuery

I have a JSON file containing the resource "A" and literals "B", "C", and "D". My goal is to extract only the items B, C, and D, convert them into strings, and store them in an array. Below is the script I have written for this purpose: <script> // ...

Transferring files to Amazon Web Services from Parse

I created an API using Node.js that enables users to upload data and media, whether it be photos or videos. AWS is configured to store the uploaded media and convert it from mp4 format to a streamable one. After completing much of the API development work ...

When first logging in, React context may initially return as undefined, but it functions correctly upon refreshing the

Currently, I am in the process of learning React Context and implementing it on a Higher Order Component (HOC) to maintain user login status throughout my application. Upon successful login, I extract the user's name from the context and display it in ...