Alexis.Rolland
Alexis.Rolland

Reputation: 6363

VueJS component does not update data

I know there is many similar questions about data not being updated in VueJS component but I still could not find the answer. I have the following component:

<template>
  <div class="mt-5">
    [...]
    <div v-for="dataSource in dataSources" v-bind:key="dataSource.id">
      {{ dataSource}}
    </div>
    [...]
  </div>
</template>

<script>
import { chain, find, merge, toUpper } from "lodash";
import Mixins from "../utils/Mixins.vue";
import Pagination from "../utils/Pagination.vue";
import DataSourceTable from "./DataSourceTable.vue";

export default {
  mixins: [Mixins],
  components: {
    "data-source-table": DataSourceTable,
    "data-source-pagination": Pagination
  },
  data: function() {
    return {
      dataSources: [],
      //[...]
    };
  },
  methods: {
    getAllDataSources(page) {
      //[...]
    },
    search() {
      //[...]
    },
    setSortAttribute(attribute) {
      //[...]
    },
    updateDataSource(updatedDataSource){
      for (let i = 0; i < this.dataSources.length; i++) {
        if (this.dataSources[i].id == updatedDataSource.id) {
          this.dataSources[i] = updatedDataSource;
          break; // Stop this loop, we found it!
        }
      }
    }
  },
  created: function() {
    this.getAllDataSources(this.currentPage);

    // Capture updated data source via websocket listener
    this.$options.sockets.onmessage = function(data) {
      let message = JSON.parse(data.data);
      if (message.id == "dataSource" && message.type == "data") {
        let updatedDataSource = message.payload.data.listen.relatedNode;
        this.updateDataSource(updatedDataSource);
      }
    }
  }
};
</script>

In the created hook, I capture changes coming from a websocket and I update the corresponding item in the array dataSources. I can see the item is properly updated in Vue Dev Tools but it is still not updated in the component template. Example below:

enter image description here

Upvotes: 1

Views: 1238

Answers (2)

Hossein Shafiei
Hossein Shafiei

Reputation: 645

When you modify an Array by directly setting an index (e.g. arr[0] = val) or modifying its length property. Similarly, Vue.js cannot pickup these changes. Always modify arrays by using an Array instance method, or replacing it entirely. Vue provides a convenience method arr.$set(index, value) which is syntax sugar for arr.splice(index, 1, value).

updateDataSource(updatedDataSource){
      for (let i = 0; i < this.dataSources.length; i++) {
        if (this.dataSources[i].id == updatedDataSource.id) {

          //this.dataSources[i] = updatedDataSource;
           this.dataSources.$set(i, updatedDataSource);
          break; // Stop this loop, we found it!
        }
      }
    }

Upvotes: 0

徐晓飞
徐晓飞

Reputation: 46

This is a common mistake with vuejs. You can check the document here: Why isn’t the DOM updating? In Your case, you can use push or $set to achieve your purpose.

When you modify an Array by directly setting an index (e.g. arr[0] = val) or modifying its length property. Similarly, Vue.js cannot pickup these changes. Always modify arrays by using an Array instance method, or replacing it entirely. Vue provides a convenience method arr.$set(index, value) which is syntax sugar for arr.splice(index, 1, value).

Example:

  • Replace this.dataSources[i] = updatedDataSource;
  • By this.dataSources.splice(i, 1, updatedDataSource);

Upvotes: 3

Related Questions