[Vuejs]-Props not updated when set from router

1👍

The counter object won’t be reactive, so property changes won’t be detected. Passing an object as a prop does not add reactivity.

I’ve just changed one line in your example:

props: (route) => ({counter: Vue.observable(new Counter(route.params.nb))}),

Passing the object to Vue.observable will apply the reactivity.

Note that ‘applying reactivity’ means rewriting all of the properties to use getters and setters. In the simple example presented here that just means the value property, which should be fine. Vue can only rewrite properties it can see, so any data hidden within closures would not be accessible.

const Home = { template: '<div>Home</div>' }
const Test = {
template: '<div>Test : {{ counter.value }}<br><button @click="addOne" type="button">+1</button></div>',
props: {counter: Object},
methods: {
  addOne() {
    this.counter.value++
    console.log('new value : ' + this.counter.value)
  }
}
}

class Counter {
  constructor(value) {
    this.value = value
  }
}

const router = new VueRouter({
  routes: [
    { path: '/', component: Home },
    {
      name: 'test',
      path: '/test/:nb',
      props: (route) => ({counter: Vue.observable(new Counter(route.params.nb))}),
      component: Test
    }
  ]
})

new Vue({
	router,
  el: '#app'
})
<script src="https://npmcdn.com/vue/dist/vue.js"></script>
<script src="https://npmcdn.com/vue-router/dist/vue-router.js"></script>

<div id="app">
  <router-link to="/">/home</router-link>
  <router-link :to="{ name: 'test', params: { nb: 42 }}">/test</router-link>
  <router-view></router-view>
</div>

Part of the reason why Vue does not automatically apply reactivity to objects passed as props is that the receiving component shouldn’t be modifying the object anyway. It’s a violation of one-way data flow. In this example you should probably be updating the route directly rather than modifying the counter object.

Leave a comment