4.3 KiB
Sprint 5 — Etapa 4C: Fix definitivo — contención de processLock al guardar perfil
Contexto
InQ ROI — React 18 + Vite + TypeScript + TanStack Router + Zustand + shadcn/ui + Tailwind + Supabase.
Etapas 1–3B completadas con OK formal. Etapa 4 completada con una excepción: guardar perfil congela la app indefinidamente.
Etapa 4B intentó corregirlo con dos fixes (guard en onAuthStateChange, useEffect de ProfileSheet con [open]). Esos fixes fueron insuficientes — el freeze persiste.
Etapa 4D (diagnóstico) confirmó la causa raíz real. Esta etapa la resuelve.
Causa raíz confirmada
Archivo: src/features/library/LibraryPage.tsx (aprox. línea 757)
useEffect(() => {
if (!user) return
load() // ← llama getSessionSafe() → intenta adquirir processLock
}, [load, user]) // ← "user" es el objeto completo, cambia de referencia en cada update
Secuencia del freeze:
- Usuario guarda perfil →
ProfileSheet.tsxllamaupdateUser({ name, company }) updateUserhacesetUser(prev => ({ ...prev, name, company }))→ nueva referencia del objetouserLibraryPagedetecta el cambio enuser→ disparaload()load()llamagetSessionSafe()→ intenta adquirirprocessLock- En paralelo, el
supabase.from('users').update(...)de ProfileSheet ya tiene o está esperandoprocessLockpara el token refresh - Contención → uno de los dos queda esperando indefinidamente → freeze
Evidencia del diagnóstico (commit dd361b1):
Los logs en producción muestran la secuencia hasta "local state updated" y luego silencio total — exactamente el momento en que setUser(...) dispara el useEffect de LibraryPage.
Fix — una línea
En src/features/library/LibraryPage.tsx, cambiar la dependencia del useEffect de user a user?.id:
// ANTES (fires en cada cambio de referencia del objeto user):
useEffect(() => {
if (!user) return
load()
}, [load, user])
// DESPUÉS (fires solo cuando cambia el ID — distinto usuario o logout/login):
useEffect(() => {
if (!user) return
load()
}, [load, user?.id])
Por qué funciona: user?.id es un primitivo estable (string). No cambia cuando updateUser crea un nuevo objeto con el mismo id pero distinto name o company. La biblioteca solo se recarga cuando hay un usuario genuinamente diferente — que es el único caso donde tiene sentido recargar.
Limpieza — remover logs de diagnóstico
El commit dd361b1 agregó console.log temporales en ProfileSheet.tsx para el diagnóstico. Removerlos todos antes del commit final.
Buscar y eliminar cualquier línea console.log con prefijo [ProfileSheet] en src/components/ProfileSheet.tsx.
Pasos de implementación
- Abrir
src/features/library/LibraryPage.tsx - Localizar el
useEffectcon dependencia[load, user]que llamaload()(aprox. línea 757) - Cambiar
user→user?.iden el array de dependencias - Abrir
src/components/ProfileSheet.tsx - Remover todos los
console.logtemporales del diagnóstico npm run build— 0 errores TypeScriptnpm run test— 528+ Vitest verdesgit push origin main— obligatorio antes de validar en producción (Dokploy no autodeploy)- Commit:
fix(sprint-5/etapa-4c): library useEffect usa user.id no user ref — corta contención processLock al guardar perfil
Qué NO entra en esta etapa
- Cambios en
processLock,getSessionSafe(), ni en el sistema de auth - Cambios en
ProfileSheet.tsxmás allá de remover los console.log - Refactoring de
LibraryPagemás allá del fix de la dependencia - Ninguna feature nueva
Criterios de validación
- Guardar nombre en el Sheet → app no se congela → nombre actualizado en el dropdown inmediatamente
- Guardar empresa en el Sheet → app no se congela → empresa aparece en el dropdown
- Cmd+R después de guardar → los valores persisten (están en Supabase)
- Navegar a la biblioteca y volver → la lista de procesos sigue correcta
- No hay
console.logde diagnóstico en la consola del browser npm run buildlimpionpm run test— 528+ Vitest verdesgit push origin mainejecutado antes de validar en producción- Validación visual del director antes del OK formal