In my vue app, I want to watch route changes, and then react to the change. Here is an example where I simulate a route change.
<script setup>
import { ref, watch } from 'vue'
import { useRouter, useRoute } from 'vue-router'
const router = useRouter()
const route = useRoute()
// simulating a route change
setTimeout(() => {
router.push('/teams/t2')
}, 2000);
// Example 1 (doesn't work)
watch(route.params.teamId, (newValue, oldValue) => {
console.log(oldValue, newValue)
})
// Example 2 (works!)
watch(() => route.params.teamId, (newValue, oldValue) => {
console.log(oldValue, newValue)
})
</script>
In example 1, I want to watch for changes of the route parameter teamId, so I pass route.params.teamId to the watcher, and I get a warning in the console saying "Invalid watch source: t2 A watch source can only be a getter/effect function, a ref, a reactive object, or an array of these types." And of course, my console.log doesn't fire.
If I simply pass route to the watcher, I don't get this warning. But the Vue Router documentation says "The route object is a reactive object, so any of its properties can be watched and you should avoid watching the whole route object. In most scenarios, you should directly watch the param you are expecting to change"
What I get from it is that route is a reactive object, but route.params.teamId is not. But why does using () => route.params.teamId work fine then? I don't understand the difference between passing the value, and using an anonymous arrow function to return that same value, and what makes one result reactive, and the other not.
I realize my question was quite stupid. I somehow assumed that whatever you give to watch() will be magically tracked somehow. It slipped my mind that we actually always give the watcher reactive properties.
For those still wondering about the function gives us "fresh" values, here's a basic example:
let numOne = 3; let numTwo = 1;
let sum = numOne + numTwo;
let getSum = () => { return numOne + numTwo }
console.log(sum) // returns 4
console.log(getSum()) // returns 4
numTwo = 2;
console.log(sum) // returns 4
console.log(getSum()) // returns 5
sum has a value that was set when it was declared. getSum() grabs the values at the moment it is called.