Loading source
Pulling the file list, source metadata, and syntax-aware rendering for this listing.
Source from repo
Vue Router 4 reference covering navigation guards, route params, lifecycle interactions, and common gotchas.
Files
Skill
Size
Entrypoint
Format
Open file
Syntax-highlighted preview of this file as included in the skill package.
reference/router-navigation-guard-next-deprecated.md
1---2title: Vue Router Navigation Guard next() Function Deprecated3impact: HIGH4impactDescription: Using the deprecated next() function incorrectly causes navigation to hang, infinite loops, or silent failures5type: gotcha6tags: [vue3, vue-router, navigation-guards, migration, async]7---89# Vue Router Navigation Guard next() Function Deprecated1011**Impact: HIGH** - The third `next()` argument in navigation guards is deprecated in Vue Router 4. While still supported for backward compatibility, using it incorrectly is one of the most common sources of bugs: calling it multiple times, forgetting to call it, or calling it conditionally without proper logic.1213## Task Checklist1415- [ ] Refactor guards to use return-based syntax instead of next()16- [ ] Remove all next() calls from navigation guards17- [ ] Use async/await pattern for asynchronous checks18- [ ] Return false to cancel, return route to redirect, return nothing to proceed1920## The Problem2122```javascript23// WRONG: Using deprecated next() function24router.beforeEach((to, from, next) => {25if (!isAuthenticated) {26next('/login') // Easy to forget this call27}28// BUG: next() not called when authenticated - navigation hangs!29})3031// WRONG: Multiple next() calls32router.beforeEach((to, from, next) => {33if (!isAuthenticated) {34next('/login')35}36next() // BUG: Called twice when not authenticated!37})3839// WRONG: next() in async code without proper handling40router.beforeEach(async (to, from, next) => {41const user = await fetchUser()42if (!user) {43next('/login')44}45next() // Still gets called even after redirect!46})47```4849## Solution: Use Return-Based Guards5051```javascript52// CORRECT: Return-based syntax (modern Vue Router 4+)53router.beforeEach((to, from) => {54if (!isAuthenticated) {55return '/login' // Redirect56}57// Return nothing (undefined) to proceed58})5960// CORRECT: Return false to cancel navigation61router.beforeEach((to, from) => {62if (hasUnsavedChanges) {63return false // Cancel navigation64}65})6667// CORRECT: Async with return-based syntax68router.beforeEach(async (to, from) => {69const user = await fetchUser()70if (!user) {71return { name: 'Login', query: { redirect: to.fullPath } }72}73// Proceed with navigation74})75```7677## Return Values Explained7879```javascript80router.beforeEach((to, from) => {81// Return nothing/undefined - allow navigation82return8384// Return false - cancel navigation, stay on current route85return false8687// Return string path - redirect to path88return '/login'8990// Return route object - redirect with full control91return { name: 'Login', query: { redirect: to.fullPath } }9293// Return Error - cancel and trigger router.onError()94return new Error('Navigation cancelled')95})96```9798## If You Must Use next() (Legacy Code)99100If maintaining legacy code that uses `next()`, follow these rules strictly:101102```javascript103// CORRECT: Exactly one next() call per code path104router.beforeEach((to, from, next) => {105if (!isAuthenticated) {106next('/login')107return // CRITICAL: Exit after calling next()108}109110if (!hasPermission(to)) {111next('/forbidden')112return // CRITICAL: Exit after calling next()113}114115next() // Only reached if all checks pass116})117```118119## Error Handling Pattern120121```javascript122router.beforeEach(async (to, from) => {123try {124await validateAccess(to)125// Proceed126} catch (error) {127if (error.status === 401) {128return '/login'129}130if (error.status === 403) {131return '/forbidden'132}133// Log error and proceed anyway (or return false)134console.error('Access validation failed:', error)135return false136}137})138```139140## Key Points1411421. **Prefer return-based syntax** - Cleaner, less error-prone, modern standard1432. **next() must be called exactly once** - If using legacy syntax, ensure single call per path1443. **Always return/exit after redirect** - Prevent multiple navigation actions1454. **Async guards work naturally** - Just return the redirect route or nothing1465. **Test all code paths** - Each branch must result in either return or next()147148## Reference149- [Vue Router Navigation Guards](https://router.vuejs.org/guide/advanced/navigation-guards.html)150- [RFC: Remove next() from Navigation Guards](https://github.com/vuejs/rfcs/discussions/302)151