Catfish
Catfish

Reputation: 19284

Unexpected side effect in computed property

I'm not sure why i'm getting an unexpected side effect in computer property error with the code below.

Error:

 ✘  https://google.com/#q=vue%2Fno-side-effects-in-computed-properties  Unexpected side effect in "orderMyReposByStars" computed property            
  src/components/HelloWorld.vue:84:14
        return this.myRepos.sort((a, b) => a.stargazers_count < b.stargazers_count)

html:

<div v-if="myRepos && myRepos.length > 0">
  <h3>My Repos</h3>
  <ul>
    <li v-for="repo in orderMyReposByStars" v-bind:key="repo.id">
      <div class="repo">
        {{repo.name}}
        <div class="pull-right">
          <i class="fas fa-star"></i>
          <span class="bold">{{repo.stargazers_count}}</span>
        </div>
      </div>
    </li>
  </ul>
</div>

js:

export default {
  name: 'HelloWorld',
  data () {
    return {
      myRepos: null,  <-- THIS IS ULTIMATELY AN ARRAY OF OBJECTS
    }
  },
  computed: {
    orderMyReposByStars: function () {
      return this.myRepos.sort((a, b) => a.stargazers_count < b.stargazers_count)
    },
...

From what I can tell this looks correct according to the docs here https://v2.vuejs.org/v2/guide/list.html#Displaying-Filtered-Sorted-Results

Upvotes: 20

Views: 33304

Answers (3)

Jacob Goh
Jacob Goh

Reputation: 20845

.sort mutates the original array.

To avoid it, clone the array before sorting it.

.slice() is 1 of the simplest way to clone array. See this answer.

return this.myRepos.slice().sort((a, b) => a.stargazers_count < b.stargazers_count)


On a side note, null.sort() or null.slice() will throw an error. Perhaps it would be better to set the initial value of myRepos to an empty array [] instead of null

Upvotes: 55

maxshuty
maxshuty

Reputation: 10662

2023 easy & readable solution...

Just the use spread syntax:

computed: {
  orderMyReposByStars: function () {
     return [...this.myRepos].sort((a, b) => a.stargazers_count < b.stargazers_count)
  },
}

Upvotes: 2

Alchie
Alchie

Reputation: 71

My Solution is to add a filter before the sort.

Array.filter(() => true).sort((a, b) => a.menu_order - b.menu_order);

Upvotes: 0

Related Questions