Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

vincent15000's avatar

Detect which item is refreshed in an array

Hello,

I have an array of components in VueJS.

I need to apply some visual effect only on the components which have been updated.

The dynamic refresh of the component is done via reloading the datas from the database.

How is it possible to identify which component has been refreshed ?

Thanks for your help.

V

0 likes
11 replies
LaryAI's avatar
Level 58

To detect which item in an array has been refreshed in Vue.js, you can use a combination of Vue's reactivity system and a unique identifier for each item. Here's a step-by-step solution:

  1. Assign a unique identifier to each item: Ensure each item in your array has a unique identifier, such as an id.

  2. Track the previous state: Keep a copy of the previous state of the array to compare with the new state.

  3. Compare the new state with the previous state: When the data is reloaded, compare the new array with the previous array to detect changes.

  4. Apply visual effects: Based on the comparison, apply the visual effects to the updated components.

Here's an example implementation:

<template>
  <div>
    <div v-for="item in items" :key="item.id" :class="{ updated: isUpdated(item.id) }">
      {{ item.name }}
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      items: [],
      previousItems: [],
      updatedItemIds: new Set()
    };
  },
  methods: {
    fetchData() {
      // Simulate fetching data from the database
      const newData = [
        { id: 1, name: 'Item 1' },
        { id: 2, name: 'Item 2' },
        { id: 3, name: 'Item 3' }
      ];

      this.detectUpdates(newData);
      this.items = newData;
    },
    detectUpdates(newData) {
      const newIds = newData.map(item => item.id);
      const previousIds = this.previousItems.map(item => item.id);

      // Find updated items
      this.updatedItemIds.clear();
      newData.forEach(item => {
        const previousItem = this.previousItems.find(prevItem => prevItem.id === item.id);
        if (previousItem && JSON.stringify(previousItem) !== JSON.stringify(item)) {
          this.updatedItemIds.add(item.id);
        }
      });

      // Update previousItems
      this.previousItems = JSON.parse(JSON.stringify(newData));
    },
    isUpdated(id) {
      return this.updatedItemIds.has(id);
    }
  },
  mounted() {
    this.fetchData();
  }
};
</script>

<style>
.updated {
  background-color: yellow;
}
</style>

Explanation:

  1. Template: The template iterates over the items array and applies a class updated to the items that have been detected as updated.

  2. Data: The items array holds the current state of the data, previousItems holds the previous state, and updatedItemIds is a set that keeps track of the IDs of updated items.

  3. Methods:

    • fetchData(): Simulates fetching data from the database and calls detectUpdates() to find updated items.
    • detectUpdates(newData): Compares the new data with the previous data to detect updates and updates the updatedItemIds set.
    • isUpdated(id): Checks if an item with the given ID is in the updatedItemIds set.
  4. Mounted Hook: Calls fetchData() when the component is mounted to initialize the data.

  5. Style: The .updated class applies a visual effect (yellow background) to the updated items.

This approach ensures that you can detect and visually highlight the components that have been updated.

MohamedTammam's avatar

I'm assuming you're talking about CSS style chagnes.

If this visual effect is when the element is added an when it's refreshes, then you can add a key to the element that changes when the value changes (make sure to prevent duplicates keys)

If this visual only when the data is updated, you can use cashing array to store the old values and check against the new ones. something similar to Lary's answer.

1 like
vincent15000's avatar

@MohamedTammam Data are retrieved from the database and then sent to the frontend. So when datas change in the array retrieved in comparison with the array already displayed, I need to apply a visual effect to the components for which the datas have changed.

martinbean's avatar

How is it possible to identify which component has been refreshed ?

@vincent15000 By using an identifier. I assume each row in your database has a value you can use to distinguish them (i.e. the id column)?

So, when an update happens, such as from a message sent via web sockets, you can update the data dynamically and also apply a CSS class that has an animation if you really want to highlight it has changed.

1 like
vincent15000's avatar

@martinbean Hmmm ... I don't see how I could apply an animation if I update the datas dynamically.

Datas have changed and effectivement the frontend receives a message from soketi saying that datas have changed. And each time I get such a message, I retrieve all items from the database table because one or several items can have changed.

So what I'm doing is items.value = res.data.data from the API call result. But in that way I don't know which items have changed from before the API call.

Perhaps I should broadcast a message via soketi with all datas that have changed and then update the frontend from these datas instead of retrieving all items from the database.

martinbean's avatar

@vincent15000 Well, no, you’re not going to know which items have updated if you just replace them all.

If you’re getting messages containing updated items, then loop over them and check if they exist in your current page of items. If it does, update it. If you’re using something like Vue.js then you can also conditionally have a class applied.

<script>
var items = ref([
  // This is your current page of items
]);

// Imagine this is your function that receives updated items from Soketi
const onItemsUpdated = (event) => {
  for (updatedItem in event.items) {
    // Look in items for item with same ID
    let index = items.value.findIndex((item) => item.id === updatedItem.id);

    // If item exists in current page...
    if (index > -1) {
      // Replace item with updated version
      items.value.splice(index, 1, updatedItem);

      // Mark item as updated so CSS class is applied
      items.value[index].updated = true;
    }
  }
};
</script>

<template>
  <ul>
    <li v-bind:class="{ 'updated': item.updated }" v-for="item in items">
      <!-- Item data -->
    </li>
  </ul>
</template>
1 like
vincent15000's avatar

@martinbean Ok so I have only 2 solutions :

  • either I retrieve all messages from the API and not only the updated messages after having received a message saying that updates are available => loop and compare each item

  • or I send only the updated datas directly via soketi => update each item received from soketi

martinbean's avatar

@vincent15000 I gave a solution based on the information you gave us.

You said that you sent an event with updated data. So why are you now saying “either I retrieve all messages from the API”? How does my example solution—again, based on the content you gave—change that?

You also have to remember that we know nothing about your application or what you’re trying to achieve. All we know is what you tell us.

martinbean's avatar
Level 80

I said that I retrieve all items from the database and not only the updated items.

@vincent15000 That’s not efficient at all, and defeats the point of using something like Soketi.

You‘re telling me if you have say, 100,000 record in your databases that you’re then doing an API request to fetch all 100,000 items over and over, and trying to work out which of them has changed?

If you’re using Soketi, then use it to broadcast changes when a record actually changes. You can then listen for the events client-side, and update the relevant records accordingly.

1 like
vincent15000's avatar

@martinbean There will never be 100 000 records in the database, perhaps max 1000 for this type of application.

But you're right, it's not efficient to retrieve all datas.

Please or to participate in this conversation.