Home > database >  Vue stopped updating state on a variable
Vue stopped updating state on a variable

Time:08-03

I had a table being populated by an axios get request, I tried implementing a Vuetify version of the table and was unsuccessful so I reverted what I did, and now I can not get any data to show in my table.

My Vue file...

<template>
  <v-container fluid>
    <div>
      <table>
        <thead>
          <tr>
            <th>ID</th>
            <th>MACID</th>
            <th>Start Time</th>
            <th>Stop Time</th>
          </tr>
        </thead>
        <tbody v-for="item in experimentList">
          <tr>
            <td>
              <strong
                ><a
                  href="#"
                  @click="
                    SetCompareInfo(
                      item.macid,
                      item.start_timestamp,
                      item.end_timestamp
                    )
                  "
                  >{{ item.experiment_id }}</a
                ></strong
              >
            </td>
            <td>{{ item.macid }}</td>
            <td>{{ item.start_timestamp }}</td>
            <td>{{ item.end_timestamp }}</td>
          </tr>
        </tbody>
      </table>
    </div>
  </v-container>
</template>

<style></style>

<script lang="ts">
import Vue from "vue";
import axios from "axios";
import { Component, Prop, Watch } from "vue-property-decorator";

@Component({
  components: {},
})
export default class ExperimentListFlow extends Vue {
  $store: any;
  experimentList: any;

  created() {
    this.GetExperiments();
    console.log(this.experimentList);
  }
  GetExperiments() {
    console.log("Inside GetExperiments");
    var machine = this.$store.state.machineName;
    console.log(machine);
    var expList = [];
    axios
      .get(this.$store.state.baseUrl   "/viruswarn/experiments")
      .then(function (response) {
        // handle success
        for (var i = 0; i < response.data.experiment_details.length; i  ) {
          if (machine == response.data.experiment_details[i].macid) {
            expList.push(response.data.experiment_details[i]);
            console.log("pushed");
          }
        }
      });
    this.experimentList = expList;
  }
  SetCompareInfo(macid, start, stop) {
    var data = {
      macid: macid,
      start: start,
      stop: stop,
    };
    this.$store.commit("storeCompareInfo", data);
    this.$router.push({ path: "/dashboard/live-plot/all/compare-plot" });
  }
}
</script>

The response from the get request...

{
  "experiment_details": [
    {
      "end_timestamp": 1658326622802,
      "experiment_details": {
        "setup": {
          "condition": "NoVirus",
          "media_addition": "Nebulization"
        }
      },
      "experiment_id": "677",
      "macid": "AA:BB:00:25:00:8B",
      "start_timestamp": 1658326584000
    },
    {
      "end_timestamp": 1658326622902,
      "experiment_details": {
        "setup": {
          "condition": "NoVirus",
          "media_addition": "Nebulization"
        }
      },
      "experiment_id": "678",
      "macid": "AA:BB:00:25:00:8B",
      "start_timestamp": 1658326584100
    },
    {
      "end_timestamp": 1659382175000,
      "experiment_details": {
        "setup": {
          "condition": "NoVirus",
          "media_addition": "Nebulization"
        }
      },
      "experiment_id": "678",
      "macid": "AA:BB:00:25:00:8B",
      "start_timestamp": 1659382171000
    },
    {
      "end_timestamp": 1659381258,
      "experiment_details": {
        "setup": {
          "condition": "NoVirus",
          "media_addition": "Nebulization"
        }
      },
      "experiment_id": "678",
      "macid": "AA:BB:00:25:00:8B",
      "start_timestamp": 1659382258
    }
  ]
}

I know the variable is being updated properly because console.log displays it correctly.

Also, if I modify the HTML only and then save the file, npm will reload the app in my browser and the data will show in the table. But it will not show when normally using the vue app.

enter image description here

And after modifying a little HTML the data shows up...

enter image description here

CodePudding user response:

As @EstusFlask pointed out, you are assigning expList to experimentList before the request gets back. At that point expList is an empty array and experimentList won't get the changes you perform to that empty array, after the request gets back.

In short, this code:

  GetExperiments() {
    console.log("Inside GetExperiments");
    var machine = this.$store.state.machineName;
    console.log(machine);
    var expList = [];
    axios
      .get(this.$store.state.baseUrl   "/viruswarn/experiments")
      .then(function (response) {
        // handle success
        for (var i = 0; i < response.data.experiment_details.length; i  ) {
          if (machine == response.data.experiment_details[i].macid) {
            expList.push(response.data.experiment_details[i]);
            console.log("pushed");
          }
        }
        // place the assignment here!
        // This happens after the `expList` has been populated
      });
    // this gets executed just after request has been sent
    // but before it has returned
    this.experimentList = expList;
  }

should be:

  GetExperiments() {
    console.log("Inside GetExperiments");
    var machine = this.$store.state.machineName;
    console.log(machine);
    var expList = [];
    axios
      .get(this.$store.state.baseUrl   "/viruswarn/experiments")
      .then((response) => {
        // handle success
        for (var i = 0; i < response.data.experiment_details.length; i  ) {
          if (machine == response.data.experiment_details[i].macid) {
            expList.push(response.data.experiment_details[i]);
            console.log("pushed");
          }
        }
        this.experimentList = expList;
      });
  }

... or, shorter version:

  GetExperiments() {
    axios
      .get(this.$store.state.baseUrl   "/viruswarn/experiments")
      .then((response) => {
        this.experimentList = response.data.experment_details.filter(
          (detail) => detail.macid == this.$store.state.machineName
        );
      });
  }

Side notes:

  • the then callback has been changed to arrow function (otherwise this.experiments can't be accessed inside it)
  • the v-for should be on <tr>, not on <tbody>.
  • the == operator should likely be replaced by ===, on general principles. Using loose equality operator is a potential source of subtle bugs, which might cost you endless hours of debugging
  • you should ditch vue-class-decorators for either clean Options API syntax or Composition API syntax. There are multiple reasons to do it, but the main one is that by using decorators you severely diminish the pool of people who can help you when you ask questions.
  • Related