I have implemented a watch
within a Vue component that displays product information. The watch
watches the route
object of vue-router
for a ProductID
param to change. When it changes, I want to go get the product details from the back-end API.
To watch the route
, I do this in Product.vue
:
import { useRoute } from 'vue-router'
export default {
setup() {
const route = useRoute();
async function getProduct(ProductID) {
await axios.get(`/api/product/${ProductID}`).then(..do something here)
}
// fetch the product information when params change
watch(() => route.params.ProductID, async (newID, oldID) => {
await getProduct(newId)
},
//watch options
{
deep: true,
immediate: true
}
)
},
}
The above code works, except that if a user navigates away from Product.vue
, for example using the back button to go back to the homepage, the watch
is triggered again and tries to make a call to the API using undefined
as the ProductID (becaues ProductID
param does not exist on the homepage route
) e.g. http://localhost:8080/api/product/undefined
. This causes an error to be thrown in the app.
watch
trigger when a user has navigated away from Product.vue
?if(newID) { await getProduct(newId) }
but it seems counterintuitive to what the watch
should be doing anyway.UPDATE & SOLUTION Place the following at the top replacing the name for whatever your route is called:
if (route.name !== "YourRouteName") {
return;
}
That will ensure nothing happens if you are not on the route you want to watch.
I ran into the same problem. Instead of watching the current route, use vue-router
onBeforeRouteUpdate
, which only gets called if the route changed and the same component is reused.
From https://next.router.vuejs.org/guide/advanced/composition-api.html#navigation-guards:
import { onBeforeRouteLeave, onBeforeRouteUpdate } from 'vue-router'
import { ref } from 'vue'
export default {
setup() {
// same as beforeRouteLeave option with no access to `this`
onBeforeRouteLeave((to, from) => {
const answer = window.confirm(
'Do you really want to leave? you have unsaved changes!'
)
// cancel the navigation and stay on the same page
if (!answer) return false
})
const userData = ref()
// same as beforeRouteUpdate option with no access to `this`
onBeforeRouteUpdate(async (to, from) => {
// only fetch the user if the id changed as maybe only the query or the hash changed
if (to.params.id !== from.params.id) {
userData.value = await fetchUser(to.params.id)
}
})
},
}