Tips for properly invoking an asynchronous function on every rerender of a component in Vue.js

Situation: An analysis module on a website that needs to display three different data tables, one at a time.

Approach: The module is a component containing three buttons. Each button sets a variable which determines which table to render. Depending on the variable value, the table calls an API for specific information.

The structure is as follows:

analysis component:

<template>
  <div class="buttons">
    <div @click="setAnalysisSection('POSITIONS')">POSITIONS</div>
    <div @click="setAnalysisSection('RESULTS')">RESULS</div>
    <div @click="setAnalysisSection('FIXTURE')"">FIXTURE</div>
  </div>
  <data-table v-if="activeAnalysis === 'FIXTURE'" data="fixture" environment="view" :loading="loading"></data-table>
  <data-table v-if="activeAnalysis === 'RESULTS'" data="results" environment="view"></data-table>
  <data-table v-if="activeAnalysis === 'POSITIONS'" data="positions" environment="view"></data-table>
</template>
<script>
import dataTable from '@/components/Table.vue';

export default {
  components: {
    'data-table' : dataTable,
  },
  data() {
    return {
      activeAnalysis: 'RESULTS',
    }
  },
  methods: {
    setAnalysisSection(section) {
      this.activeAnalysis = section;
    }
  },
}
</script>

table component:

<template>
  <div>
    <table class="table__fixture">
      <thead>
        <tr>
          <td>DATE</td>
          <td>TIME</td>
          <td>CONFIRMATION</td>
        </tr>
      </thead>
      <tbody>
        <tr v-if="tableData.data" v-for="row in tableData.data" :key="row.id">
          <td>{{row.date | date}}</td>
          <td>{{row.time | time}}</td>
          <td>{{row.zone}}</td>
        </tr>
      </tbody>
    </table>
    <table class="table__postions">
      <thead>
        <tr>
          <td>POSITION</td>
          <td>PTS</td>
          <td>PLAYED</td>

        </tr>
      </thead>
      <tbody>
        <tr v-if="tableData.data" v-for="row in tableData.data" :key="row.id">
          <td>{{row.position}}</td>
          <td>{{row.points}}</td>
          <td>{{row.played}}</td>
        </tr>
      </tbody>
    </table>
    <table class="table__results">
      <thead>
        <tr>
          <td>DATE</td>
          <td>TIME</td>
          <td>CONFIRMATION</td>
        </tr>
      </thead>
      <tbody>
        <tr v-if="tableData.data" v-for="row in tableData.data" :key="row.id">
          <td>{{row.date | date}}</td>
          <td>{{row.time | time}}</td>
          <td>{{row.zone}}</td>
        </tr>
      </tbody>
    </table>
  </div>
</template>
<script>
import axios from 'axios';

export default {
  props: ['data', 'environment'],
  data() {
    return {
      tableData: '',
    };
  },
  mounted() {
    if (this.data === 'fixture' && this.environment === 'view') {
      this.fetch('fixture', 1, 15);
    } else if (this.data === 'positions') {
      this.fetch('positions', 1, 100);
    } else if (this.data === 'results') {
      this.fetch('results', 1, 15);
    }
  },
  methods: {
    async fetch(data, page, perPage) {
      console.log('Fetching data!');
      const self = this
      if (data === 'fixture') {
        try {
          const response = await axios.get(`apilinkhere/public/fixture?page=${page}&per_page=${perPage}`);
          self.tableData = response.data;
        } catch (error) {
          throw new Error(error);
        }
      } else if (data === 'positions') {
        try {
          const response = await axios.get(`apilinkhere/positions?page=${page}&per_page=${perPage}`);
          self.tableData = response.data;
        } catch (error) {
          throw new Error(error);
        }
      } else if (data === 'results') {
        try {
          const response = await axios.get(`apilinkhere/public/results?page=${page}&per_page=${perPage}`);
          self.tableData = response.data;
        } catch (error) {
          throw new Error(error);
        }
      }
    },
  },
};
</script>

Issue:

The problem lies in the fact that the mounted hook only executes once during the initial rendering of the component, not upon each subsequent render (such as when changing the activeAnalysis). Alternatively, utilizing the Updated hook for calling the API method for different table data, as suggested in the documentation, results in an infinite loop of method calls.

According to Vue's documentation, watching a variable could solve this issue. However, it may be unclear where and how to implement this watch functionality.

NOTE:

You might notice discrepancies in the provided code (filters applied to variables in the template that are not defined in the script, for instance). This was done to enhance readability by cleaning up the copied code. Any language inconsistencies are due to the original code being partially written in Spanish and do not affect the core problem or necessary information for providing a solution.

Answer №1

Resolution:

To resolve the issue, I implemented a watcher on the "data" property.

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

Display content exclusively within a modal specifically designed for mobile devices

I want to implement a feature where a button triggers a modal displaying content, but only on mobile devices. On desktop, the same content should be displayed in a div without the need for a button or modal. For instance: <div class="container&quo ...

Basic HTML Audio Player Featuring Several Customizable Variables

I have a unique API that manages music playback. Instead of playing audio in the browser, it is done through a Discord bot. Achievement Goal https://i.stack.imgur.com/w3WUJ.png Parameters: current: indicates the current position of the track (e.g. 2:3 ...

While attempting to use JavaScript and AJAX to read a JSON object, I encountered an issue caused by the CORS

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Docu ...

Using Javascript to attach <head> elements can be accomplished with the .innerHTML property, however, it does not work with XML child nodes

Exploring new ways to achieve my goal here! I want to include one JS and one jQuery attachment for each head section on every page of my static website. My files are: home.html <head> <script src="https://ajax.googleapis.com/ajax/libs/jquer ...

Simply click and drag a document from your file explorer directly into the desired text field to instantly generate a clickable

I am interested in dragging a file from our Windows server and dropping it onto a text area on a webpage. The link that would be generated will look something like this: <a href="\\fileserver\folder\pizza_2.pdf">filename.pdf< ...

Error Loading Collada Texture: Three.js Cross Origin Issue

I'm encountering an issue with loading a Collada file using three.js that has a texture called Texture_0.png associated with it. The Collada file and the texture are stored in the same blob and accessed via a REST Web Service. CORS is enabled, allowin ...

Showcasing top performers via JavaScript tabs

I have two tabs on my webpage: "Overall Leaderboard" and "Weekly Leaderboard". Each tab displays a leaderboard with different scores. When I click on the "Overall Leaderboard" tab, it shows a leaderboard with specific scores. Now, my question is how can ...

Obtain the origin of the image using dots in Javascript

Sharing my experience with setting a background image using Javascript. Initially, I tried using two dots like this: .style.backgroundImage = "url('../images/image00.jpg')" However, it did not work as expected. So, I removed one dot: .style.ba ...

The quirks of JSON.stringify's behavior

I am in the process of gathering values to send back to an ASP.NET MVC controller action. Despite using JSON.stringify, I keep encountering Invalid JSON primitive exceptions and I am unsure why. I have a search value container named searchValues. When I i ...

Utilize Android accelerometer data to bring objects to life with animation

Utilizing an Android app, I am streaming accelerometer data to a Python script on my PC. The data is then saved to a text file. My goal is to utilize Javascript and jQuery to animate a 3D CSS cuboid (representing the device) to replicate the movements capt ...

Cookies in Node.js Express are not being incorporated

Currently, I am in the process of developing a nodejs application and facing an issue with defining cookies. Here is a snippet of the code that I am working with: var app = express(); app.set('port', process.env.PORT || 3000); app.set('vie ...

A guide on accessing JavaScript files from the components directory in a React Native iOS application

I am encountering difficulty in accessing the components folder within my React Native Project on IOS. The error message I am receiving is: Unable to resolve module ./Login from ....../ReactNative/ReactNativeProject/components/App.js: Unable to find ...

Using jQuery to crop an SVG view box

I'm currently working on a sticker website project for a client who requires the ability to crop an image within a specific SVG shape, resembling a Halloween face (shown below). The uploaded image should be displayed only within this shape while hidi ...

Using JavaScript to reduce, group, and sum nested objects

I'm a third-year student working on my first internship project and struggling with organizing and aggregating data from a JSON object. The goal is to group the data by name, calculate total weight per name, and sum up the grades for each entry. I&apo ...

Formatting dates in JavaScript

When using the jQuery datepicker, my goal is to set a minimum and maximum date range for users to select from. I also need to ensure that the date format is based on the user's locale. In this case, there are two date fields: Start date and End date. ...

Vue.js v-for dynamically creates HTML blocks that capture the state of collapse with two-way data binding

I am currently working on capturing the click action state within an HTML v-for generated block for a collapsible function. I have set up a data table and it seems that the state is being captured correctly. However, I am facing an issue where the displa ...

The asynchronous functionality of Azure IoT Edge node SDK's invokeDeviceMethod seems to be malfunctioning

I am attempting to asynchronously return a result for a direct method call. This is what I attempted: const client = Client.fromConnectionString(process.env.AZ_IOT_CONNECTION_STRING); const methodParams = { methodName: "method", payload: 10, // Numbe ...

Controlling worldwide modules using Node Version Manager

Currently, I am utilizing nvm as a tool to manage node.js / io.js versions, encountering difficulties with global modules every time I update node. Recently, I attempted to install npm i express-generator -g. I noticed an older version in /usr/local/bin a ...

getStaticProps only runs on IIS after the entire page is refreshed

Using the nextjs getStaticProps feature in my project has been smooth sailing so far. However, after uploading the Static files to IIS, the feature seemed to stop working until I configured a urlRewrite module on it. I noticed that when initially visiting ...

Combining Ajax Form with Django to handle and display errors in form submissions

I am attempting to save information from a form into my Database using Django and Python for the backend. Below is the HTML form: <form> <center> <div class="container-fluid"> <div class="row"> <div clas ...