title: Vue Router 4: How to add/push a new URL entry without causing routing push?
body: <p>I think this is the most common asked question about Vue Router but with no clear answer or suggestion to deal with it.</p>
  <p><strong>What I have?</strong></p>
  <p>1- A view with multiple components (Main, Navigation, Pagination, Filtering).</p>
  <p>2- Using state management 'Pinia' to update the data that being shown in (Main) component whenever there is an action ( clicking a <code>&lt;router-link&gt;</code> ) in the other components.</p>
  <p>3- a piece of the code:</p>
  <pre class="lang-html prettyprint-override"><code>
  &lt;router-link 
    :to=&quot;{ 
        path: useRoute.path,
        params: { ...useRoute.params},
        query: { ...useRoute.query, page: pageNumber}
    }&quot; 
    @click.capture.prevent=&quot;updateData(pageNumber)&quot;
  &gt;
    &lt;span&gt; {{pageNumber}} &lt;/span&gt;
  &lt;/router-link&gt;
  
  </code></pre>
  <p><strong>What I get?</strong></p>
  <p>Update the data successfully in (Main) component but I can't update the URL query parameter (page) due using of event:</p>
  <p><code>@click.capture.prevent</code></p>
  <p>That's stop the default behavior of the <code>&lt;router-link&gt;</code> which is navigate to the route that specified in <code>:to=&quot;{}&quot;</code></p>
  <p><strong>What I DON'T want?</strong></p>
  <p>1- Using:</p>
  <pre><code>history.pushState()
  </code></pre>
  <p>will lead to cause issues to the Router because it can't track the changes those made to the URL and so a malfunction will occur within Router navigation.</p>
  <p>2- Using:</p>
  <pre><code>useRouter.push()
  </code></pre>
  <p>Will lead to make a push to the route that set in <code>push()</code> function.</p>
  <p><strong>What I want?</strong></p>
  <p>Update the URL and Router history in the same time without causing router navigation or malfunction to the Router.</p>
  <p><strong>If you are interesting to see the code:</strong></p>
  <p>@/router/index.js</p>
  <pre class="lang-java prettyprint-override"><code>
  import { createRouter, createWebHistory } from 'vue-router';
  import HomeView from '../views/HomeView.vue';
  
  const routes = [
    {    
      name: 'home',
      path: '/home',
      alias: ['/'],
      component: HomeView
    },
    {
      name: 'store',
      path: '/store/:slug?/:subSlug?/:page?',
      component: () =&gt; import(/* webpackChunkName: &quot;store&quot; */ '../views/StoreView.vue'),
      props: route =&gt; ({
        slug: route.params.slug,
        subSlug: route.params.subSlug,
        page: route.query.page
      })
      
    },
    {
      name: &quot;page-not-found&quot;,
      path: &quot;/:pathMatch(.*)*&quot;,
      component: () =&gt; import(/* webpackChunkName: &quot;not-found&quot; */ &quot;../views/PageNotFoundView.vue&quot;)
    }
  ]
  
  const router = createRouter({
    history: createWebHistory(),
    routes
  });
  
  export default router
  </code></pre>
  <p>StoreView.vue</p>
  <pre class="lang-html prettyprint-override"><code>
  &lt;template&gt;
  
      &lt;section class=&quot;section-content padding-y&quot;&gt;
  
        &lt;div class=&quot;container&quot;&gt;
      
            &lt;StoreMain /&gt;
            &lt;PaginationComponent /&gt;
  
        &lt;/div&gt;
  
      &lt;/section&gt;
  
  &lt;/template&gt;
  
  &lt;script&gt;
  import StoreMain from &quot;@/components/StoreMainComponent&quot;;
  import PaginationComponent from &quot;@/components/PaginationComponent&quot;; 
  import {usePaginationStore} from &quot;@/store/Pagination&quot;;
  import {defineProps} from &quot;vue&quot;;
  import router from &quot;@/router&quot;;
  
  export default {
    name: &quot;StoreView&quot;,
    components: {
      StoreMain,
      PaginationComponent
  
    }
  }
  
  &lt;/script&gt;
  
  &lt;script setup&gt;
  
  /*
    Define handlers (properties, props and computed)
  */
  
  const props = defineProps({
    slug: {
      type: String,
      required: false
    },
    subSlug: {
      type: String,
      required: false
    },
    page: {
      type: String,
      required: true
    }
  });
  const storePagination = usePaginationStore();
  
  const triggerGetDataResult = async () =&gt; {
  
    await storePagination.getDataResult(URLToBackend + (`?page=${props.page}`));
  
  await triggerGetDataResult();
  
  &lt;/script&gt;
  
  &lt;style scoped&gt;
  
  &lt;/style&gt;
  </code></pre>
  <p>StoreMainComponent.vue</p>
  <pre class="lang-html prettyprint-override"><code>&lt;template&gt;
  
    &lt;div class=&quot;row&quot;&gt;
  
      &lt;main class=&quot;col-md-12&quot; &gt;
  
      &lt;!-- Process the data stored in the Store --&gt;
      
      &lt;/main&gt; 
  
    &lt;/div&gt;
  
  &lt;/template&gt;
  
  &lt;script&gt;
  
  import {usePaginationStore} from &quot;@/store/Pagination&quot;;
  
  export default {
    name: &quot;StoreMainComponent&quot;
  }
  
  &lt;/script&gt;
  
  &lt;script setup&gt;
  
  const storePagination = usePaginationStore();
  storePagination.$subscribe((mutation, state) =&gt; {});
  
  &lt;/script&gt;
  
  &lt;style scoped&gt;
  
  &lt;/style&gt;
  
  </code></pre>
  <p>PaginationComponent.vue</p>
  <pre class="lang-html prettyprint-override"><code>
  &lt;template&gt;
  
    &lt;nav class=&quot;mt-4&quot; aria-label=&quot;Page navigation sample&quot;&gt;
      &lt;ul class=&quot;pagination justify-content-center&quot;&gt;
        &lt;li class=&quot;page-item&quot;&gt;
          &lt;router-link
              :to=&quot;{ path: route.path, query: { ...route.query, page: +page - 1 } }&quot;
              class=&quot;page-link&quot;
              @click.capture.prevent=&quot;changePage(+page - 1)&quot;
          &gt;
            &lt;span&gt; Previous &lt;/span&gt;
          &lt;/router-link&gt;
        &lt;/li&gt;
  
        &lt;li class=page-item&quot; &gt;
          &lt;router-link
              :to=&quot;{ path: route.path, query: { ...route.query, page: +page + 1 } }&quot;
              class=&quot;page-link&quot;
              @click.capture.prevent=&quot;changePage(+page + 1)&quot;
              &gt;
            &lt;span&gt; Next &lt;/span&gt;
          &lt;/router-link&gt;
        &lt;/li&gt;
      &lt;/ul&gt;
    &lt;/nav&gt;
  
  &lt;/template&gt;
  
  &lt;script&gt;
  
  import {usePaginationStore} from &quot;@/store/Pagination&quot;;
  import {useRoute} from &quot;vue-router&quot;;
  import {ref} from &quot;vue&quot;;
  
  export default {
    name: &quot;PaginationComponent&quot;
  }
  
  &lt;/script&gt;
  
  &lt;script setup&gt;
  
  const storePagination = usePaginationStore();
  const route = useRoute();
  const page = ref(+route.query.page);
  
  const changePage = async (pageNumber) =&gt; {
  
       // Change pageNumber in store which will trigger the 'getDataResult' function in store.
       await storePagination.changePageNumber(pageNumber, URLToBackend);
     }
  };
  
  &lt;/script&gt;
  
  &lt;style scoped&gt;
  
  &lt;/style&gt;
  
  </code></pre>
  <p>@/store/Pagination.js</p>
  <pre class="lang-java prettyprint-override"><code>
  import {defineStore} from 'pinia';
  import {axios} from &quot;@/common/api.axios&quot;;
  
  export const usePaginationStore = defineStore('Pagination', {
    state: () =&gt; ({
      data: [],
      dataResult: [],
      dataLoading: false
    }),
    actions: {
  
      async changePageNumber(page, endpoint) {
  
        return this.getDataResult(endpoint + `?page=${page}`);
      },
  
      async getDataResult(endpoint) {
  
        this.dataLoading = true;
        try {
          this.data = await axios.get(endpoint);
          this.dataResult = this.data.data.results;
        }
        catch (error){
          console.log(&quot;Error while trying to retrieve the requested data from backend server!&quot;);
        }
        finally {
          this.dataLoading = false;
        }
      }
    },
  });
  
  </code></pre>
  <p><em><strong>Finally</strong></em>, I really appreciate your answers and suggestions (not too complex) to solve this manner.</p>