yeti blue
yeti blue

Reputation: 271

Using array.sort() on Vue data() variable

I'm loading Api data into a reactive variable called 'MyListings', and attempting to sort it based on latest id -> earliest id.

The problem I'm having is that since array.sort is an 'in-place' function it overwrites the original array which causes the Vue page to infinitely re-render.

Is there some way to clone the data out of data()? (I tried setting a constant to this.MyListings which produced the same results as the original)

api data

 [
        {
          id: 1,
          title: "sdf",
          start_date: "2021-01-13",
          poster:
            "http://localhost:8000/media/images/2-Artwork-by-Tishk-Barzanji_iZookmb.jpg",
          genre: "Action"
        },
        {
          id: 3,
          title: "ooga booga",
          start_date: "2021-01-07",
          poster: "http://localhost:8000/media/images/1_bdm0Lld.jpg",
          genre: "Thriller"
        }
      ];

Relevant Vue bits

updated() {
    this.sortedArray();
  },
 data() {
    return {
      genre: "",
      MyListings: []
    };
  },
methods: {
    // no access to AsnycData in components, handle the incoming data like axios in vanilla vue.
    memberListings($axios) {
      this.$axios
        .get("/api/v1/memberlistings/")
        .then(response => {
          // console.log(response, "response");
          this.MyListings = response.data;
        })
        .catch(error => {
          console.log(error);
        });
    },

    formSubmit() {
      this.update(); //all dropdown combinations below include a POST request
    },
    update() {
      if (this.genre !== "") {
        console.log("genre submitted");
        this.$axios
          .get(`/api/v1/memberlistings/`, {
            params: {
              genre: this.genre
            }
          })
          .then(response => {
            this.MyListings = response.data;
          })
          .catch(error => {
            console.log(error);
          });
      } else {
        this.$axios
          .get(`/api/v1/memberlistings/`)
          .then(response => {
            this.MyListings = response.data;
          })
          .catch(error => {
            console.log(error);
          });
      }
    },
    sortedArray() {
      const sortedMyListings = this.MyListings;
      sortedMyListings.sort((a, b) => b.id - a.id);
      console.log(sortedMyListings, "sortedlist");
      console.log("works");
    }
  }

**This is what the endless rendering looks like in console log **



  [1]: https://i.sstatic.net/CTVAH.png

Upvotes: 0

Views: 1504

Answers (1)

Nilesh Patel
Nilesh Patel

Reputation: 3317

I believe, you want to display data in sorted order. hence, you should create a computed property.

computed:{
  sortedData() {
    return this.MyListings.map(item=>item).sort((a,b)=> a.id - b.id)
  }
},

and use that computed property in template

<template>   
  <div id="app">
    <div v-for="item in sortedData" :key="item.id">
      {{item.id}}-{{item.title}}
    </div>
  </div>
</template>

Upvotes: 1

Related Questions