El proyecto WiFi Card es una aplicación React que permite generar códigos QR para compartir redes WiFi. A medida que los usuarios modifican parámetros como el nombre de la red o la contraseña, una implementación deficiente puede provocar renderizados completos del árbol de componentes, afectando la fluidez en dispositivos con recursos limitados. Este artículo presenta técnicas concretas para reducir renderizados superfluos y acelerar la respuesta de la aplicación.
¿Por qué es crucial optimizar el rendimiento en WiFi Card?
En interacciones típicas, el usuario ajusta repetidamente campos del formulario. Sin una estrategia de optimización, cada cambio puede desencadenar la rerenderización de todo el componente raíz, incluyendo aquellos que no consumen los datos modificados. Esto genera latencia y una experiencia pobre, especialmente en hardware modesto. La clave está en aislar los componentes que realmente necesitan actualizarse.
Patrones que generan renderizados innecesarios
- Propagación de actualizaciones del padre a hijos no afectados: Un cambio en el estado del componente padre fuerza la rerenderización de todos sus hijos, aunque estos no dependan de dicho estado.
- Creación de nuevas funciones en cada renderizado: Las funciones definidas dentro del cuerpo del componente se recrean con cada ejecución, lo que modifica las referencias pasadas como props a componentes hijos.
- Cálculos repetitivos dentro del renderizado: Operaciones costosas (como transformar datos o generar el código QR) que se ejecutan en cada ciclo de render sin necesidad.
Técnica 1: Emplear React.memo en componentes de presentación
React.memo es un高阶组件 que realiza una comparación superficial de las props. Si estas no han cambiado, el componente no se rerenderiza. Es ideal para componentes puramente visuales como WifiCard, que solo reciben datos estáticos.
const WifiCard = React.memo(function WifiCard({ ssid, qrCode }) {
// Renderizado del código QR y nombre de red
});
Técnica 2: useCallback y useMemo para evitar referencias y cálculos redundantes
En componentes como Settings, los manejadores de eventos deben conservar su identidad. Con useCallback se mantiene la misma referencia de función mientras las dependencias no cambien.
const handleSsidChange = useCallback((event) => {
setSsid(event.target.value);
}, []); // La función es estable
Para evitar recalcular datos derivados, useMemo almacena el resultado hasta que las entradas varíen. Ejemplo con la generación del código QR:
const qrContent = useMemo(() => {
return buildQRPayload(ssid, password, encryption);
}, [ssid, password, encryption]);
Técnica 3: Fragmentar el árbol de componentes
Dividir App en subcomponentes independientes limita el alcance de las rerenderizaciones. Por ejemplo, separar SettingsForm de QRDisplay permite que solo el formulario se actualice al escribir en los campos, mientras que el código QR solo se regenera cuando los datos de red cambian realmente.
Verificación de los resultados
Con las herramientas de desarrollo de React (pestaña Profiler) se puede inspeccionar qué componentes se rerenderizan y cuánto tiempo consumen. Una aplicación optimizada mostrará actualizaciones solo en los componentes cuyas props o estado hayan mutado, con tiempos de render reducidos y una interfaz más receptiva.