Fix: Eliminar race condition en sincronización del icono de toggle
Some checks failed
build-and-deploy / build-and-deploy (push) Has been cancelled
Some checks failed
build-and-deploy / build-and-deploy (push) Has been cancelled
Problema:
- El icono del toggle mostraba comportamiento inconsistente entre páginas
- Algunas páginas cargaban con icono correcto (hamburguesa) y otras con "X"
- Race condition entre múltiples watchers compitiendo por el estado
Causa raíz detectada:
1. DashboardSidebar.vue:58 tiene watcher con {immediate:true} que sincroniza
nuestro composable → contexto de DashboardGroup
2. DashboardSidebar.vue:60 tiene watcher que cierra sidebar en navegación
3. Nuestro composable TAMBIÉN tenía un watcher de navegación (duplicado)
4. Múltiples watchers registrándose cada vez que se llama useSidebarState()
5. Race condition: dependiendo del orden de montaje de componentes,
el toggle podía leer el estado antes o después de la sincronización
Solución:
- Eliminar completamente el watcher de navegación de nuestro composable
- Dejar que DashboardSidebar de Nuxt UI maneje el cierre en navegación
- Nuestro composable solo mantiene el estado, no lógica de ciclo de vida
- Evita múltiples registros de watchers
- Elimina la race condition
Cambios:
- Removido watcher de route.fullPath (líneas 110-116)
- Removidas importaciones innecesarias (watch, useRoute)
- Actualizado comentario del header
- Simplificado: composable ahora es puramente state management
Resultado:
✓ Icono consistente en todas las páginas
✓ No más race conditions
✓ Menos watchers = mejor performance
✓ DashboardSidebar maneja toda la lógica de navegación
Referencias:
- app/composables/useSidebarState.ts:14
- app/composables/useSidebarState.ts:29
This commit is contained in:
@@ -8,11 +8,10 @@
|
||||
* - Estado persistente en cookies
|
||||
* - Sincronización automática entre open/collapsed
|
||||
* - Manejo de responsive (mobile vs desktop)
|
||||
* - Cierre automático en navegación (solo mobile)
|
||||
* - DashboardSidebar de Nuxt UI maneja el cierre en navegación
|
||||
*/
|
||||
|
||||
import { ref, computed, watch } from 'vue'
|
||||
import { useRoute } from 'vue-router'
|
||||
import { ref, computed } from 'vue'
|
||||
|
||||
// Storage key para las cookies
|
||||
const STORAGE_KEY = 'analytics-dashboard-sidebar'
|
||||
@@ -28,8 +27,6 @@ interface SidebarState {
|
||||
const sidebarState = ref<SidebarState | null>(null)
|
||||
|
||||
export function useSidebarState() {
|
||||
const route = useRoute()
|
||||
|
||||
// Detectar si estamos en mobile (debe hacerse antes de leer el estado)
|
||||
const isMobile = computed(() => {
|
||||
if (import.meta.server) return false
|
||||
@@ -106,15 +103,6 @@ export function useSidebarState() {
|
||||
collapsed.value = value
|
||||
}
|
||||
|
||||
// Auto-cerrar en navegación solo en mobile
|
||||
if (import.meta.client) {
|
||||
watch(() => route.fullPath, () => {
|
||||
if (isMobile.value) {
|
||||
open.value = false
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
return {
|
||||
// Estado
|
||||
open,
|
||||
|
||||
Reference in New Issue
Block a user