Vuex Router Sync
The `vuex-router-sync` library provides a straightforward utility to keep `vue-router`'s current route state synchronized with a `vuex` store. Its core `sync` function injects the current route object into the Vuex state, typically at `store.state.route`, enabling reactive access to route parameters, query strings, and path information directly from the store. This simplifies component logic that depends on route data, reducing the need to pass `$route` explicitly. The current stable version, 5.0.0, is compatible with `vue-router >= 3.0.0` and `vuex >= 3.0.0` and includes comprehensive TypeScript definitions. A release candidate for v6.0.0 is under development, targeting compatibility with the Vue 3 ecosystem (Vuex 4, Vue Router 4). The package has a consistent release cadence, typically aligning with major version updates of Vue's core routing and state management libraries. It differentiates itself by offering a simple, drop-in solution for a common integration pattern.
Common errors
-
Property 'route' does not exist on type 'Store<RootState>'
cause Common TypeScript error when `vuex-router-sync` has been initialized, but the TypeScript compiler doesn't know about the injected `route` property on the Vuex store's state.fixYou need to augment the Vuex Store interface to include the `route` property. Create a declaration file (e.g., `shims-vuex-router-sync.d.ts`) with: ```typescript import 'vuex'; import { Route } from 'vue-router'; declare module 'vuex' { interface Store<S> { readonly state: S & { route: Route }; } } ``` -
TypeError: Cannot assign to read only property 'path' of object '#<Object>'
cause This error occurs when you attempt to directly modify the `store.state.route` object, which is immutable since v2.0.0.fixTo change the current route, use the `vue-router` instance's methods like `router.push('/new-path')` or `router.replace({ name: 'routeName' })`. -
Uncaught TypeError: (0 , vuex_router_sync_1.sync) is not a function
cause This usually indicates an incorrect import statement, especially in a mixed CommonJS/ESM environment, or if `vuex-router-sync` was not correctly installed.fixEnsure you are using `import { sync } from 'vuex-router-sync';` for ESM. For CommonJS (older Node.js), it would be `const { sync } = require('vuex-router-sync');`. Also, verify the package is listed in `package.json` and `node_modules`. -
npm ERR! ERESOLVE unable to resolve dependency tree ... npm ERR! Peer dependency 'vue-router@^3.0.0' not installed
cause The installed versions of `vue-router` or `vuex` do not satisfy the peer dependency requirements of `vuex-router-sync` (e.g., trying to install v5 with Vue Router 2).fixEnsure your `vue-router` and `vuex` versions meet the requirements. For `vuex-router-sync` v5.x, you need `vue-router` >= 3.x and `vuex` >= 3.x. Update or downgrade peer dependencies as needed, or consider `npm install --legacy-peer-deps` as a temporary workaround (not recommended for production).
Warnings
- breaking Version 6.0.0 (currently in release candidate) introduces breaking changes for compatibility with Vue 3, Vuex 4, and Vue Router 4. Applications on Vue 2 should remain on `vuex-router-sync` v5.
- breaking For TypeScript users, `vuex-router-sync` v5.0.0 updated its type declarations to be compatible exclusively with `vuex >= 3.0.0` and `vue-router >= 3.0.0`. Older versions are no longer supported by the types.
- breaking In `vuex-router-sync` v4.0.0, the payload for the internal `router/ROUTE_CHANGED` mutation was updated from `{ to }` to `{ to, from }`. If you have custom Vuex plugins or watchers explicitly listening to this mutation, their logic may break.
- gotcha Since `vuex-router-sync` v2.0.0, the `store.state.route` object is intentionally made immutable. Attempting to directly mutate this object (e.g., `store.state.route.path = '/new-path'`) will not trigger navigation and may lead to errors or inconsistent state.
Install
-
npm install vuex-router-sync -
yarn add vuex-router-sync -
pnpm add vuex-router-sync
Imports
- sync
const sync = require('vuex-router-sync').sync;import { sync } from 'vuex-router-sync'; - SyncOptions
import type { SyncOptions } from 'vuex-router-sync'; - VuexRouterSyncState
import type { VuexRouterSyncState } from 'vuex-router-sync';
Quickstart
import Vue from 'vue';
import Vuex from 'vuex';
import VueRouter from 'vue-router';
import { sync } from 'vuex-router-sync';
Vue.use(Vuex);
Vue.use(VueRouter);
const routes = [
{ path: '/', component: { template: '<div>Home Page</div>' } },
{ path: '/about', component: { template: '<div>About Page</div>' } },
{ path: '/users/:id', component: { template: '<div>User ID from store: {{ $store.state.route.params.id }}</div>' } }
];
const router = new VueRouter({
routes
});
const store = new Vuex.Store({
state: {
appData: 'Initial Application Data'
},
getters: {
currentRoutePath: state => state.route.path // Access route info from store
}
});
// Synchronize Vue Router with Vuex store
sync(store, router);
new Vue({
router,
store,
template: `
<div id="app">
<h1>Vuex Router Sync Example</h1>
<p>Current path (from Vuex store): <strong>{{ $store.state.route.path }}</strong></p>
<p>Current path (from Vue Router): <strong>{{ $route.path }}</strong></p>
<nav>
<router-link to="/">Home</router-link> |
<router-link to="/about">About</router-link> |
<router-link to="/users/42">User 42</router-link>
</nav>
<hr>
<router-view></router-view>
</div>
`
}).$mount('#app');