[Analizando esto sistemáticamente...]
Primero, déjame ayudarte a diagnosticar el problema correctamente:
Preguntas para reducir la causa:
- ¿Cuándo crece la memoria? (¿en cambio de ruta, montaje/desmontaje de componente, interacciones de usuario?)
- ¿Estás usando características de React 18+ (transiciones, Suspense)?
- ¿Qué muestra el Heap Snapshot de Chrome DevTools como reteniendo memoria?
Culpables más probables en React moderno:
1. Event Listeners (Clásico)
useEffect(() => {
window.addEventListener('resize', handler)
// Falta: return () => window.removeEventListener('resize', handler)
}, [])
2. Bibliotecas de terceros manteniendo referencias
- Bibliotecas de gráficos (Chart.js, D3) no destruidas apropiadamente
- Conexiones WebSocket no cerradas
- Escenas, cámaras, renderizadores de Three.js no dispuestos
3. Problemas específicos de React 18+:
- Características concurrentes creando múltiples instancias de componentes
- Actualizaciones de estado después del desmontaje (busca advertencias de "Can't perform a React state update on unmounted component")
4. Trampas de closure:
const handler = useCallback(() => {
// Capturando accidentalmente todo el scope del componente
console.log(largeData)
}, []) // Deps vacías = captura valores iniciales para siempre
Estrategia de diagnóstico:
- Usar React DevTools Profiler para identificar qué componente
- Tomar heap snapshots antes/después de la acción que causa la fuga
- Buscar "Detached HTMLElement" o closures retenidos
- Verificar limpieza faltante en useEffect/useLayoutEffect
Tip de herramientas modernas: Habilitar React Strict Mode - intencionalmente monta componentes dos veces para exponer bugs de limpieza durante desarrollo.
¿Quieres que revise un componente específico? Comparte el código y puedo identificar el problema exacto.