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:

https://i.sstatic.net/c5DKg.png

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

Issue with Vuetify Combobox: Value not updating accurately

Whenever I try to save a value from my Vuetify combobox, it seems to store the previously selected value instead of the new one if I click the save button directly without deselecting the combobox. The correct value is only stored when I manually unselect ...

Unable to modify variable to play audio

As I work on constructing my website, I am incorporating various sounds to enhance user experience when interacting with buttons and other elements. However, managing multiple audio files has proven challenging, as overlapping sounds often result in no aud ...

What are the steps to assign a variable by selecting a link from a list that is automatically generated?

After generating a list from a query, everything is working smoothly. Now, I want to use jQuery to trigger an event that will set a PHP variable for me. The scenario is simple - I have a table with 'column 1' and 'column 2'. Each link ...

How about this: "Can you turn a picture into text with just one click?"

Seeking assistance to enhance the 'About Us' page on our website. Each team member has a profile with their email address listed below, but we want to add a picture that disappears when clicked, revealing the email address in its place. You can ...

VueJS Vuetify automatically centers default content

Vue cli version @ 5.0.6 | Vuetify version: [email protected] I have been utilizing Vue.js and Vuetify for some time now, and I can't shake the feeling that not all Vue.js/Vuetify components default to centered alignment. I recently initialized a ...

What is the process for creating a custom hook in React.js/Next.js?

I encountered a problem while trying to create a hook from my code. Here is the snippet from the hook file: import { useRouter } from "next/router"; const useCurrentPath = () => { const { asPath, locale, defaultLocale } = use ...

Receiving an error of "undefined" when trying to capture the selected

One issue I am facing is capturing the selected user option and sending that value in a post request. Let's put aside the post part since it's not directly related to the main question at hand. Currently, the value is showing up as undefined. ...

Exploring the possibilities of maximizing, minimizing, resizing, and creating a responsive design in dialog boxes using jQuery UI JavaScript and

I'm trying to create a dialog with maximize, resize, and minimize buttons like those found in Windows OS. I want the dialog to be responsive and draggable as well. I've been using jQuery, jQuery UI, and extended dialog frameworks, but I haven&apo ...

Guide on inserting text within a Toggle Switch Component using React

Is there a way to insert text inside a Switch component in ReactJS? Specifically, I'm looking to add the text EN and PT within the Switch Component. I opted not to use any libraries for this. Instead, I crafted the component solely using CSS to achie ...

Is there a way to determine if a React functional component has been displayed in the code?

Currently, I am working on implementing logging to track the time it takes for a functional component in React to render. My main challenge is determining when the rendering of the component is complete and visible to the user on the front end. I believe t ...

How can a JavaScript function be used to check a tag's status?

I currently have two select tags on my webpage. I want to ensure that only one option can be selected at a time from these two tags. If the user tries to select options from both tags, an error message should be displayed instructing them to choose only on ...

Exploring the JSON data in Javascript using Ajax

Completely new to Javascript, I am just trying to grasp the basics of the language. Currently, I have a JSON request set up with the following code: function request(){ $.ajax({ dataType: "jsonp", type: 'GET', url: "getWebsite", ...

React Side Panels that Collapse and Expand

Apologies if this task seems simple, as I am new to transitioning to React. My current application is primarily built with JavaScript, CSS, and HTML, and I am now looking to migrate it to React. There is a full-length horizontal side panel that is initiall ...

Is there a way to determine where a Javascript event originated from when it was triggered programmatically?

In my current debugging situation, I am investigating why pressing Enter on a submit button triggers a 'click' event on that same button. It appears that the click event is being fired programmatically, which is the expected behavior in the appli ...

What causes Node.js to be unable to handle requests from Vue.js?

I'm encountering a strange error where Node.js is unable to see the URL address and consistently returns a 404 error. In my Vue.js application, I am making a post request using the axios package when the user clicks a button. The code snippet shows t ...

Accessing index.html via file:// from Vue-cli template

Whenever I execute the npm run build command using this Vue-cli template, it displays this message: Hint: The built files are designed to be served over an HTTP server. Attempting to open index.html via file:// will not function correctly. Therefore, the ...

Unable to refresh the fullcalendar section following an ajax post click

Currently developing a calendar using fullcalendar. I have created an ajax button that retrieves events from another php page. The first click on the ajax button works fine, displaying a nice month calendar with events. However, my issue arises when I cl ...

jQuery wrapAll issue

I have a repeating group of three divs in my code that I need to wrap together. Here's an example from my HTML: <div class="one" /> <div class="two" /> <div class="three" /> <div class="one" /> <div class="two" /> <d ...

Encountering special symbols in the ID of a form element triggers an error message in jQuery validator, stating 'Unrecognized expression'

One of the challenges I am facing is that I have a form with elements that have ids containing special symbols. For example: The id="$FormData[1]$PersonData[1]$PhysicalPerson[1]$PersonName[1]$Affix[@type='qualification' and @position='prefi ...

Adding a uniform header and footer across all pages simultaneously in HTML

I am currently working on a project where I want to apply the same header and footer design from my homepage to all pages. However, I need a method that allows me to update the header and footer in one place, so that any changes I make will automatically r ...