vuejs3vue-routervue-router4

beforeEnter navigation guard not triggering when router.push() is called on the same route


I have a search engine which is not properly updating when after having searched something, I try to search something else.

When I want to search something, the search function in the search component is called:

function search() {
    const searchTerm = '/search=' + encodeURI(term.value.value)
    console.log('search', term.value.value, question, searchTerm)
    router.push(searchTerm)
}

My vue-router for the /search=:question is as follow:

  {
    path: "/search=:question",
    name: "search",
    component: SearchView,
    beforeEnter: async (to) => {
      await store.commit('setQuestion', to.params.question)
      console.log('beforeEnter', store.state.question)
      await store.dispatch('fetchSearchResult')
    }
  }

It works as intended when I am doing the search from /, as you can see from the messages in the console:

search What is the meaning of life? undefined /search=What%20is%20the%20meaning%20of%20life? SearchComp.vue:25
beforeEnter What is the meaning of life index.js:32

Except when I'm doing the search from /search=What%20is%20the%20meaning%20of%20life, the beforeEnter navigation guard is not called but the url still changes to searchTerm:

search How come Kropotkin looks like Santa? What is the meaning of life? /search=How%20come%20Kropotkin%20looks%20like%20Santa? SearchComp.vue:25

I tried doing a setup with a parent and a child route to force vue to trigger before enter but it hasn't worked.

  {
    path: "/search",
    name: "search",
    children: [
      {
        path: ":question",
        name: "searchQuestion",
        component: SearchView,
        beforeEnter: async (to) => {
          await store.commit('setQuestion', to.params.question)
          console.log('beforeEnter', store.state.question)
          await store.dispatch('fetchSearchResult')
        }
      }
    ]
  }

I also tried using beforeEach but its not suited for this use case given that I need to fetch stuff from my backend. I guess that router.push() is just not made to trigger beforeEnter. If thats the case I should probably call search, update the store and use ref to force update my components but I'd much rather use router.push if possible.


Solution

  • As it says in the documentation:

    beforeEnter guards only trigger when entering the route, they don't trigger when the params, query or hash change e.g. going from /users/2 to /users/3 or going from /users/2#info to /users/2#projects. They are only triggered when navigating from a different route.

    Instead, put a watcher on the search property of the route:

    const route = useRoute()
    
    watch(
      () => route.params.search,
      async (searchTerm) => {
          await store.commit('setQuestion', searchTerm)
          await store.dispatch('fetchSearchResult')
        }
    )
    

    this is described in more details here