This package provides a plugin for @riogz/router that maintains persistent parameters across route transitions.
npm install @riogz/router-plugin-persistent-paramsA router plugin that maintains persistent parameters across route transitions, making them "sticky" throughout the navigation session.
``bash`
npm install @riogz/router-plugin-persistent-params
This plugin ensures that specified parameters are automatically included in all route transitions. It's particularly useful for maintaining user preferences, theme settings, locale information, or debug flags across your entire application.
`typescript
import { createRouter } from '@riogz/router'
import persistentParamsPlugin from '@riogz/router-plugin-persistent-params'
const router = createRouter([
{ name: 'home', path: '/' },
{ name: 'profile', path: '/profile/:userId' },
{ name: 'settings', path: '/settings' }
])
// Make theme and locale persistent
router.usePlugin(persistentParamsPlugin(['theme', 'locale']))
router.start()
// Navigate with persistent parameters
router.navigate('profile', { userId: '123', theme: 'dark' })
// URL: /profile/123?theme=dark
// Later navigation automatically includes theme
router.navigate('settings')
// URL: /settings?theme=dark
`
Creates a persistent parameters plugin factory.
#### Parameters
- config (PersistentParamsConfig): Configuration for persistent parametersstring[]
- : Array of parameter names (parameters start as undefined)Record
- : Object with parameter names as keys and default values
#### Returns
- PluginFactory: A plugin factory function for use with router.usePlugin()
When using an array, parameters will be undefined initially and only become persistent when first set during navigation.
`typescript
router.usePlugin(persistentParamsPlugin(['theme', 'locale', 'debug']))
// Parameters start as undefined
router.navigate('home') // URL: /
// Set a parameter
router.navigate('profile', { userId: '123', theme: 'dark' })
// URL: /profile/123?theme=dark
// Theme is now persistent
router.navigate('settings')
// URL: /settings?theme=dark
`
When using an object, parameters have default values and are included in all routes from the start.
`typescript
router.usePlugin(persistentParamsPlugin({
theme: 'light',
locale: 'en',
debug: false
}))
// All routes include default parameters
router.navigate('home')
// URL: /?theme=light&locale=en&debug=false
// Override specific parameters
router.navigate('profile', { userId: '123', theme: 'dark' })
// URL: /profile/123?theme=dark&locale=en&debug=false
`
`typescript
// Simple theme switching
router.usePlugin(persistentParamsPlugin({ theme: 'auto' }))
// Toggle theme
function toggleTheme() {
const currentRoute = router.getState()
const newTheme = currentRoute.params.theme === 'dark' ? 'light' : 'dark'
router.navigate(currentRoute.name, {
...currentRoute.params,
theme: newTheme
})
}
`
`typescript
// Locale persistence
router.usePlugin(persistentParamsPlugin({ locale: 'en' }))
// Change language
function setLanguage(locale: string) {
const currentRoute = router.getState()
router.navigate(currentRoute.name, {
...currentRoute.params,
locale
})
}
`
`typescript
// Development/debug parameters
router.usePlugin(persistentParamsPlugin({
debug: process.env.NODE_ENV === 'development',
verbose: false,
showGrid: false
}))
// Enable debug mode
router.navigate('current-route', { debug: true })
`
`typescript
// UI state persistence
router.usePlugin(persistentParamsPlugin([
'sortBy', // Table sorting
'filterBy', // Active filters
'viewMode', // List/grid view
'pageSize' // Items per page
]))
// Set user preferences
router.navigate('products', {
sortBy: 'price',
filterBy: 'electronics',
viewMode: 'grid',
pageSize: '20'
})
// Preferences persist across navigation
router.navigate('categories') // Still has sortBy, filterBy, etc.
`
The plugin operates by:
1. Modifying the root path: Adds persistent parameters as query parameters to the router's root path
2. Decorating navigation methods: Automatically merges persistent parameters into buildPath and buildState calls
3. Listening to transitions: Updates persistent parameter values when they change during successful transitions
`typescript
// Before plugin
router.navigate('profile', { userId: '123' })
// URL: /profile/123
// After plugin with persistent theme
router.navigate('profile', { userId: '123' })
// URL: /profile/123?theme=light (theme automatically added)
// Update persistent parameter
router.navigate('profile', { userId: '123', theme: 'dark' })
// URL: /profile/123?theme=dark (theme value updated)
// Navigate elsewhere
router.navigate('settings')
// URL: /settings?theme=dark (theme persists)
`
The plugin includes full TypeScript definitions:
`typescript
import persistentParamsPlugin, {
PersistentParamsConfig,
persistentParamsPluginFactory
} from '@riogz/router-plugin-persistent-params'
// Type-safe configuration
const config: PersistentParamsConfig = {
theme: 'light' as 'light' | 'dark',
locale: 'en' as string,
debug: false as boolean
}
router.usePlugin(persistentParamsPlugin(config))
`
`typescript
// hooks/useTheme.ts
import { useRouter } from '@riogz/react-router'
export function useTheme() {
const router = useRouter()
const state = router.getState()
const setTheme = (theme: string) => {
router.navigate(state.name, {
...state.params,
theme
})
}
return {
theme: state.params.theme || 'light',
setTheme
}
}
// components/ThemeToggle.tsx
import { useTheme } from '../hooks/useTheme'
export function ThemeToggle() {
const { theme, setTheme } = useTheme()
return (
)
}
`
`typescript
// Sync with localStorage
router.usePlugin(persistentParamsPlugin({
theme: localStorage.getItem('theme') || 'light'
}))
// Listen for changes and update localStorage
router.subscribe((toState) => {
if (toState.params.theme) {
localStorage.setItem('theme', toState.params.theme)
}
})
`
Use descriptive, consistent parameter names:
`typescript
// ✅ Good
router.usePlugin(persistentParamsPlugin([
'uiTheme',
'userLocale',
'debugMode'
]))
// ❌ Avoid
router.usePlugin(persistentParamsPlugin([
't',
'l',
'd'
]))
`
Provide sensible defaults for better UX:
`typescript
// ✅ Good - users see consistent UI immediately
router.usePlugin(persistentParamsPlugin({
theme: 'light',
locale: navigator.language.split('-')[0] || 'en',
animations: true
}))
// ❌ Avoid - undefined values can cause UI flicker
router.usePlugin(persistentParamsPlugin(['theme', 'locale']))
`
- Limit the number of persistent parameters (recommended: < 10)
- Use simple values (strings, numbers, booleans) rather than complex objects
- Consider URL length limitations for many parameters
Ensure the plugin is registered before starting the router:
`typescript
// ✅ Correct order
router.usePlugin(persistentParamsPlugin(['theme']))
router.start()
// ❌ Wrong order
router.start()
router.usePlugin(persistentParamsPlugin(['theme'])) // Too late!
`
If you have many persistent parameters, consider using shorter names or storing complex state in localStorage:
`typescript``
// Instead of many URL parameters
router.usePlugin(persistentParamsPlugin({
sessionId: generateSessionId() // Store complex state by ID
}))
MIT
Issues and pull requests are welcome on GitHub.