Nick Res
Nick Res

Reputation: 2244

Vue Object isn't returning updated value despite seeing the value updated

I'm writing tests for Vue.js and I'm trying to write the test to ensure that when some props are changed for pagination, the resulting values within the component are updated properly.

So when I console.log the component, I see the correctly updated values, but then when I try to literally grab that attribute it gives me the old and outdated value. Look at rangeList in the following screenshot to see what I mean:

enter image description here

Here is my code so that you see how what is generating this output.

pagComp.$refs.component.limit = 10;
pagComp.$refs.component.pages = 145;
console.log(pagComp.$refs.component);
console.log('RangList: ' + pagComp.$refs.component.rangeList.length);  

Here is the code that modifies rangeList:

 createListOfRanges() {
   let range = [];
   for(let i = 0; i < this.pages; i++) {
     range.push(i);
   }
   this.rangeList = [];
   while(range.length > 0) {
     this.rangeList.push(range.splice(0, this.rangeLength));
   }
   this.correctLastRange();
 },     

Finally, there are two places this function is called: when the component is being created, and when the pages attribute changes. Here is the watcher:

watch: {
 pages(val) {
   this.createListOfRanges();
 }

},

Upvotes: 0

Views: 85

Answers (3)

Nick Res
Nick Res

Reputation: 2244

I appreciate the answers above, however they aren't what the issue was.

The problem was with Vue's lifecycle. I'm not 100% sure why, but when the page and limit variables are changed it takes another moment for the page watcher (shown above) to get executed and update the component. So thus it wouldn't show up in my tests. So what I did was use nextTick like so, which fixed the problem.

pagVue.limit = 10;  // limit and pages change together every time automatically
pagVue.pages = 145;
Vue.nextTick(() => {
  expect(pagination.rangeList.length).toBe(25);
})

Upvotes: 0

Justin MacArthur
Justin MacArthur

Reputation: 4050

While @Mani is right on the line of code giving you issues is your push to rangeList.

createListOfRanges() {
  let range = [];
  for(let i = 0; i < this.pages; i++) {
    range.push(i);
  }

  this.rangeList = [];
  while(range.length > 0) {
    this.rangeList.push(range.splice(0, this.rangeLength));
  }
  this.correctLastRange();
},

pushing the result of the splice just makes a single element with all the elements of range in it.

try changing it to

this.rangeList.push(range.shift());

Though your function could be simplified by pushing the for(let i = 0; i < this.pages; i++) { i value directly to rangeList unless that's a simplification.

This JSFiddle shows what I'm talking about.

Upvotes: 1

Mani Jagadeesan
Mani Jagadeesan

Reputation: 24275

I see some issues with this part of your code:

while(range.length > 0) {
    this.rangeList.push(range.splice(0, this.rangeLength));
}

range.splice(..) returns an array, which is getting pushed into this.rangeList

Forget about that for a minute. Look at the following example:

x = [1, 2, 3, 4]
x.splice(0, 2)  // result: [1, 2]

As you can see above, splice returns an array, not an element. Now, in the same example above:

x = [1, 2, 3, 4]
y = [10, 11]
y.push(x.splice(0, 2))

Check the value of y. It will be [10, 11, [1, 2] ]. It is an array within another array. It does not look very meaningful here. You can do the above x and y experiments directly in your developer console.

In your case, your x happens to be the local range array within createListOfRanges method, and your y is this.rangeList that belongs to your Vue component.

Can you check your app logic at around that area, and see if that is really what you want to do?

For debugging Vue.js apps, you also need Vue devtools: https://github.com/vuejs/vue-devtools - it is much better than console.log()

Upvotes: 1

Related Questions