Reputation: 315
I have a component with some items and those items are loaded from api using get request
method. When I click on an item I get redirected to its own page using dynamic routing: { path: '/:id', component: Item }
. Clicked item is recognised using currentItem()
method: currentItem() { this.items.find(item => item.code === this.$route.params.id) }
where item.code
is a property I get from api.
My problem is that when I refresh the page with current item, it is not loaded anymore. I tried using beforeCreate()
to load items one more time in their own component. Maybe I could use a watch
to change the state depending on the item?
beforeCreate() {
this.$http.get(url).then(response => {
this.items = response.body;
}
},
watch: {
'$route' (to, from) {
this.currentItem()
}
}
Here's a demo.
Upvotes: 2
Views: 7534
Reputation: 6034
You should add watch
for $route
to react to id
changes when you navigate between pages. But in this case there is a chance that currentItem
return null because your request will have ended after watch handler already invoked.
First solution is to watch items
collection in Item
component and invoke this.currentItem()
in this watch handler. And yes, you will have to load items
in your Item
component like in your example.
Second one is use computed
property currentItem
instead method if it's possible:
computed: {
currentItem() {
return this.items.find(item => item.code === this.$route.params.id)
}
}
This will be reactive and you don't need watch anymore. But don't forget to make this.items
empty array by default to avoid null errors.
The third solution is combination second one with using Vuex store to share items collection between all components and do something like this:
beforeCreate() {
// you should check in this action that items already loaded earlier as well
this.$store.dispatch('loadItems');
},
computed: {
currentItem() {
return this.items.find(item => item.code === this.$route.params.id)
},
items() {
return this.$store.state.items
}
}
Store:
state: {
items: [],
itemsLoaded: false,
}
actions: {
loadItems({state, commit}) {
// avoid unnecessary loading between navigations
if (itemsLoaded) return
Vue.http.get('some url').then(response => {
commit('setItems', response.body);
commit('itemsLoaded');
}
}
},
mutations: {
setItems: (state, items) => state.items = items
itemsLoaded: (state) => state.itemsLoaded = true
}
So you dont need to store items in both Item and Items components for example.
Sorry for long post.
Upvotes: 1