20

Cómo depurar componentes con React Profiler y React Developer Tools

49166Puntos

hace 3 años

Pensar en el rendimiento de tu aplicación es fundamental para pasar al siguiente nivel con React. Y para esto necesitas identificar aquellos componentes que puedan ser algo costosos de renderizar.

A simple vista no podemos hacerlo, aunque React nos provee su API Profiler para medir la frecuencia con la que se renderizan los componentes de nuestras apps y el costo de este renderizado. Así podremos tener una buena referencia de los lugares en los cuales necesitamos mejorar nuestro código.

¿Qué vas a necesitar para depurar componentes?

De entrada no tendrás que agregar nada extra en tus proyectos. Esta API viene por defecto en React y puedes obtener sus métricas envolviendo tus componentes dentro de Profiler. No es la única forma de hacer uso de esta API, ya que también puedes usar extensiones para tu navegador que te proporcionarán una vista general del tiempo de carga de todos tus componentes (una alternativa muy buena que tampoco requiere una configuración adicional).

Tanto en la tienda de extensiones de Firefox como de Chrome podrás encontrar esta extensión con el nombre de React Developer Tools, te dejo el enlace directo aquí abajo: 👇🏻

React Profiler en acción

Al importar el componente de Profiler le tendrás que pasar las siguientes props para que pueda hacer las mediciones sin problema alguno:

  • Id
  • onRender
  • React children

Teniendo en mente esto ya podrás agregarlo de la siguiente forma:

// Example.jsximport React, { Profiler } from'react'const MyApp = () => {
  functiononRenderCallback(id, phase, actualDuration,baseDuration, startTime, commitTime, interactions) {
    console.table({id, phase, actualDuration,baseDuration, startTime, commitTime})
  }
	...
  return (
    
// 👇🏻 Nuestro React children
) }

Puedes usar multiples profilers dentro de un solo componente. Incluso podrías anidar profilers si así lo necesitas. Recuerda que la presencia del componente Profiler no afecta de manera considerable el rendimiento, pero debes tener cuidado con no agregar más de los necesarios y recordar que debes mantenerlos solo para hacer las mediciones.

Ahora déjame hablarte un poco sobre la función que recibe el callback. Como habrás visto en el código de ejemplo, recibe 7 parámetros los cuales son los siguientes:

  • id: el ID que le proveímos a nuestro profiler
  • phase: fase de nuestro componente la cual puede ser mount(después de ser montado) o update(después de cada renderizado)
  • actualDuration: tiempo dedicado a procesar la actualización confirmada
  • baseDuration: estimación sobre el tiempo para renderizar todo el subárbol (los componentes hacía abajo que pudiese llegar a tener) sin memoización
  • startTime: tiempo cuando React comenzó a procesar la actualización actual
  • commitTime: tiempo en el que React confirmó la actualización
  • interactions: conjunto de interacciones pertenecientes a esta actualización

Ejemplo práctico

✨ Preparé para ti un pequeño proyecto en este codepen para que puedas observar en la practica cómo sacarle el mayor provecho a esta API

Te invito a ver el Codepen para que observes que tenemos dos componentes envueltos dentro de y veas en la consola que cada que cambias de personaje se despliegan resultados similares a estos :

Values
  1. En primer lugar, obtenemos una actualización del componente de Character que sucede al instante después de pulsar uno de los botones para desplegar el texto de “Loading…”.

  2. El segundo es una actualización que tiene nuestro Footer la cual no debería suceder porque no estamos haciendo ningún cambio en el (Aunque la diferencia es apenas de un par de mili-segundos se puede bajar a 0).

  3. El ultimo valor son los resultados una vez que se tiene la data de la API.

Para hacer más notorios los renders que tiene el footer puedes agregar una referencia con useRef, esta actualizará cada que se haga un nuevo render del componente.

const CounterNormal = ({ name }) => {
  const count = useRef(0)
  
  return(
    <div><p>Hello {name}p><p>Total of re-renders: {(count.current++)} p>div>
  )
}

Esta son re-renders innecesarios que hace React, pero puedes evitarlos usando la Memoización (la cual ayuda a React a “Memorizar” sus componentes), para el caso tan sencillo de nuestro Footer solo baste en envolverlo de la siguiente forma con React.memo().

const Footer = React.memo(functionFppter({ name }) {
  const count = useRef(0)
  
  return(
    <footer><p>Hello {name} p><p>Total of re-renders: {(count.current++)}p>footer>
  )
}) 

Esto nos otorgará unas mediciones en consola como las siguientes (en las cuales podemos notar que nuestro footer ya no se actualiza aunque salga como update, los tiempos de startTime y commitTime son los mismos).

Values with meoization

React Developer Tools

¿Recuerdas que más atrás en este blog te hablé de las React Developer Tools? Es un recurso mucho más visual que usar el componente profiler que igual que este, solo puedes usarlo en modo desarrollo en tus aplicaciones hechas con React.

Para empezar a utilizar esta extensión abre las herramientas de desarrollador y tendrás una pestaña llamada Profiler. Basta con darle al botón azul y empezar a interactuar con tu aplicación para que esta registre todos esos tiempos de respuesta.

enter image description here

Una vez terminado, el profiler te arrojará unos resultados de una forma mucho más gráfica como los siguientes:

Results

💡 Cuando ocupas las React developer tools no es necesario que utilices el componente de Profiler, lo dejé dentro del proyecto para que puedas ver que esta extensión mide todo lo que tenga tu App

  1. Las etiquetas anaranjadas son los componentes que tardaron más en cargar en relación a los demás, App al ser el contenedor de todo es la parte que más tiempo demora, por obvias razones
  2. Las etiquetas verdes son las que más rápido cargan
  3. Las etiquetes entre anaranjado y vede son aquellas que tardan un poco más de lo que deberían, el componente de Profiler es extremadamente liviano y es por eso que una milesima de segundo más en el se considera como mucho tiempo.
  4. Las etiquetas grises o transparentes como el caso de Footer son aquellas que no tienen un renderizado ya que ocupan técnicas como la de Memoización que te comenté antes

Da el siguiente paso con React

Te platiqué apenas muy por encima sobre React.memo() y la Memoización, un par de conceptos que mejoran significativamente el rendimiento en tus proyectos, pero no son las únicas herramientas que existen, de hecho React tiene múltiples hooks y utilidades para seguir mejorando este aspecto.

👀 ¿Te gustaría aprender a profundidad como usarlos? Déjamelo saber aquí abajo en los comentarios

Y no puedo despedirme sin antes dejarte una serie de cursos para seguir mejorando como React Developer

#NuncaParesDeAprender

Leonardo de los angeles
Leonardo de los angeles
LeoCode0

49166Puntos

hace 3 años

Todas sus entradas
Escribe tu comentario
+ 2
3
25548Puntos
3 años

Este es el resultado del profiler a mi proyecto del Curso de Introducción a React.js
Captura de Pantalla 2021-12-06 a la(s) 11.04.25.png

2
49166Puntos
3 años

Hola Gustavo

¡Te quedó increíble!
¿Crees que aún puedes optimizar tu proyecto 👀?

3
25548Puntos
3 años

Hola Leo!
Justo ayer en la noche terminé el Curso de Introducción a React del profe JuanDC!
Y ahora leo este estupendo post.
Voy a probar el profiler con la App que hicimos de proyecto del curso.
Muchas gracias!