What steps can I take to avoid unnecessary re-rendering of a variable that is not utilized in the HTML of my vue.js component?

I am currently in the process of replicating a real-life example of my code. In the actual code, this line represents a component that will continuously fetch an endpoint every few seconds, retrieving a random array of length "n", encapsulated within the variable myData.

<div v-for="item in addingData(myData)">  <!-- In the live code, "myData" is the response from an endpoint based on setInterval, returning data like [{id:1},{id:2}] -->
  {{ item.id }}
</div>

To simulate dynamic changes in the response stored in myData, I am utilizing the setTimeOut function.

mounted() {
  setTimeout(() => {
    console.log('First data');
    this.myData = [{ id: 3 }, { id: 2 }, { id: 1 }];
    setTimeout(() => {
      console.log('second data');
      this.myData = [{ id: 4 }, { id: 4 }];
      setTimeout(() => {
        console.log('Third data');
        this.myData = [];
      }, 3000);
    }, 3000);
  }, 2000);
},

The goal is to present a concatenated list of unique data items each time new data is received in myData. This behavior is achieved by calling the function addingData(myData) which performs the concatenation operation. The function

v-for="item in addingData(myData)
utilizes the variable auxData for this purpose.

The issue arises where the addingData function is unintentionally triggered twice when new data is received. How can this redundancy be prevented?

In terms of performance, the expected output in the console.log should resemble the following:

What leads to this re-rendering and what strategies can be employed to mitigate it?

This is the link to the live code:

https://stackblitz.com/edit/vue-l7gdpj?file=src%2FApp.vue

<template>
  <div id="app">
    <div v-for="item in addingData(myData)">
      {{ item.id }}
    </div>
  </div>
</template>
<script>
import HelloWorld from './components/HelloWorld.vue';

export default {
  name: 'App',
  data() {
    return {
      myData: [],
      auxData: [],
    };
  },
    mounted() {
      setTimeout(() => {
        console.log('First data');
        this.myData = [{ id: 3 }, { id: 2 }, { id: 1 }];
        setTimeout(() => {
          console.log('second data');
          this.myData = [{ id: 4 }, { id: 4 }];
          setTimeout(() => {
            console.log('Third data');
            this.myData = [];
          }, 3000);
        }, 3000);
      }, 2000);
    },
  methods: {
    addingData(getDataFetch) {
      console.log('Entering AddingData', getDataFetch);
      if (getDataFetch.length !== 0) {
        if (this.auxData.length === 0) {
          //Adding initial data
          this.auxData = getDataFetch;
        } else {
          //Preventing duplication of values
          getDataFetch.forEach((item) => {
            const isNewItem = this.auxData.find((itemAux) => {
              return item.id === itemAux.id;
            });
            if (!isNewItem) {
              //Adding new data 
              this.auxData.unshift(item);
            }
          });
        }
      } else {
        //Returning empty array if no data present
        return this.auxData;
      }
    },
  },
};
</script>

Answer №1

From what I gather, you are looking to merge unique objects into an array obtained from various API calls and display them in a template using the v-for directive. If this is correct, you can accomplish this by utilizing a computed property.

Since you are updating the myData with each response, you can create a separate array for unique objects and then return that array using a computed property.

Take a look at this Live Demo:

new Vue({
  el: '#app',
  data: {
    combinedData: [],
    myData: []
  },
  mounted() {
    setTimeout(() => {
      console.log('First data');
      this.myData = [{ id: 3 }, { id: 2 }, { id: 1 }];
      this.pushData(this.myData)
      setTimeout(() => {
        console.log('Second data');
        this.myData = [{ id: 4 }, { id: 4 }];
        this.pushData(this.myData)
        setTimeout(() => {
          console.log('Third data');
          this.myData = [];
          this.pushData(this.myData)
        }, 3000);
      }, 3000);
    }, 2000);
  },
  methods: {
    pushData(data) {
      data.forEach(obj => {
        if (!JSON.stringify(this.combinedData).includes(JSON.stringify(obj))) {
          this.combinedData.push(obj)
        }
      });
    }
  },
  computed: {
    finalData() {
        return this.combinedData
    }
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
  <div v-for="item in finalData">
    {{ item.id }}
  </div>
</div>

Answer №2

When it comes to efficiency, the console.log output should look like this:

Efficiency-wise, it's best to minimize the use of reactive data, especially if your object has numerous properties. Directly modifying auxData would be a better approach.

 this.addingData([{ id: 3 }, { id: 2 }, { id: 1 }]);

A streamlined version of addingData

addingData(getDataFetch) {
  // Getting the ids first is quicker
  let itemDict = new Set(this.auxData.map((m) => m.id));
  getDataFetch.forEach((item) => {
    if (!itemDict.has(item.id)) {
      this.auxData.unshift(item);
      itemDict.add(item.id);
    }
  });
},

And then looping through it

<div v-for="item in auxData">
  {{ item.id }}
</div>

Additionally, watching lists of objects can lead to performance issues. It's more suitable for primitive values.

Check out the example on StackBlitz

Answer №3

It appears that utilizing v-for with auxData is essential, considering that's the data being updated by the response from your API call (myData). To keep up-to-date with new results from your API, implement a watcher to trigger a function each time an update occurs, ensuring auxData reflects these changes.

View the updated stackblitz here

watch: {
    myData(newData, oldData) {
      console.log('Entering AddingData', newData);
      if (newData.length !== 0) {
        if (this.auxData.length === 0) {
          this.auxData = newData;
        } else {
          newData.forEach((item) => {
            const isNewItem = this.auxData.find((itemAux) => {
              return item.id === itemAux.id;
            });
            if (!isNewItem) {
              this.auxData.unshift(item);
            }
          });
        }
      }
    },
  },
<div v-for="item in auxData">
  {{ item.id }}
</div>

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

Issues with Firefox Protractor testing functionality

Trying to test a protractor on an angularjs application using Firefox 47 has been unsuccessful. Attempted downgrading to version 46.0.1 after researching on Stack Overflow, but still facing issues. Has anyone discovered a working solution for this? It seem ...

Utilize React without integrating a router component

For my web application built with reactjs, I am considering creating a multi-page site rather than a single page. Should I bundle all the react code into one file and include it on every page of the application, then utilize the exposed function to render ...

Asynchronous setTimeout for server-side operations

I am currently facing an issue with my web server. Whenever a request is made, the server initiates a phone call, waits for 3 seconds, and then checks if the call is still ongoing. I have utilized setTimeout to achieve this functionality, but it seems to b ...

Issues encountered when setting up a Context Provider in React using TypeScript

I am currently in the process of setting up a Cart context in my React TypeScript project, inspired by the implementation found here: https://github.com/AlexSegen/react-shopping-cart/blob/master/src/contexts/CartContext.js. I'm encountering some conf ...

Unable to retrieve HTML content through a Node.js server

I created a HTML webpage that includes .css, images and JavaScript files. However, when I start my node server using the command below: app.get('/', function(req, res){ res.sendFile(__dirname + '/index.html'); }); The webp ...

Tips for preserving login status even after the browser is shut down with the help of JavaScript

I need help with maintaining a user session in my chat application even when the browser is closed. After users log in for the first time, I want their credentials to be remembered by the browser (I'm currently using local storage). How can I ensure ...

How can I transfer data to a different component in Angular 11 that is not directly related?

Within the home component, there is a line that reads ...<app-root [message]="hii"> which opens the app-root component. The app-root component has an @input and {{message}} in the HTML is functioning properly. However, instead of opening t ...

What Causes the "Not a String or Buffer Type" Unhandled Exception?

I've encountered an error that seems to be originating from the following line of code, even though I believe I am following the example correctly (viewable at https://www.npmjs.org/package/aws-sign). Any help or hints would be greatly appreciated. v ...

Tips for implementing daterangepicker js in an Angular 2 project

I'm currently working on an Angular 2 project and I'm looking to integrate the daterangepicker.js library for a date range picker. If you're not familiar with it, you can find more information about the library here. Here's the HTML co ...

As the height is expanded, the background color gradually infiltrates the body of the page

I am currently working on an angular application that utilizes angular-pdf. The controller and view function perfectly, and the PDF is displayed correctly, except for one issue. The height of the PDF exceeds the min-height of the module, causing it to expa ...

What is causing onbeforeunload to consistently display a dialog box?

I'm facing an issue where my javascript code displays a confirmation dialog even when there is no unsaved data. I have simplified the problem to this bare minimum: window.addEventListener("beforeunload", (e) => { e.returnValue = null; retu ...

Laravel vue infinite scroll failing to load additional content

I've been trying to implement the infinite scroll feature from Element UI in my app, but for some reason, it's just not working. Here's a snippet of my code: Code script // Your JavaScript code goes here ...

Insert a division into the table following every row

I'm working with a table that can be found here: https://codepen.io/anon/pen/bjvwOx Whenever I click on a row (for example, the 1st row 'NODE ID 1'), I want the div with the id #divTemplate to appear below that particular row, just like it d ...

Exploring the world of jQuery animation and background colors with Animate()

I'm currently attempting to implement a basic pulse effect by utilizing JQuery to modify the background color. However, I am facing issues with animating the backgroundColor property. function show_user(dnid) { /* dnid represents the HTML ID of a ...

Getting a URL path in Next.js without relying on the Link component when the basePath is configured

Base Path from the next.js documentation states: For instance, by setting basePath to /docs, /about will automatically transform into /docs/about. export default function HomePage() { return ( <> <Link href="/about"> ...

The website is failing to extend and reveal content that is being concealed by jQuery

I'm currently diving into the world of Javascript and jQuery, attempting to create a functionality where upon clicking the submit button, the website dynamically expands to display search information. Although the feature is still in progress, I am ut ...

Creating a customized SelectField component for Material-UI v1.0.0-alpha.21 with a fix for the Menu anchorEl problem

Currently, Material-UI v1.0.0 does not have a selectField implemented yet so I am attempting to create my own version using TextField, Menu, and MenuItem Components. Below is the code for my custom selectField: export default class SelectField extends Rea ...

Major Technical Issues Plague School-wide Celebration

In my JavaScript code, I am creating a 16x16 grid of divs. Each div should change its background color from black to white when the mouse enters (inherited based on a common class). However, I am facing an issue where all the divs change color simultaneou ...

How can you trigger a page method from a layout event in Vue.js?

I'm working on a design that includes a sidebar and an image gallery on the page. Initially, all images are loaded without any filters applied. However, when a button in the sidebar is clicked, I want the page to display filtered images. Although I ca ...

The appearance of Recaptcha buttons is unattractive and seemingly impossible to

Let me start by saying that I have already looked into the issue of "Recaptcha is broken" where adjusting the line-height was suggested as a solution. Unfortunately, that did not work for me. After implementing Google's impressive Recaptcha on my web ...