Hook de optimización de rendimiento useMemo en React
El primer hook para optimización del
rendimiento que veremos
es useMemo.
Este hook ayuda a almacenar en caché los resultados de operaciones que consumen muchos recursos entre los momentos de repintado de la pantalla y, en consecuencia, puede ayudar a evitar cálculos voluminosos innecesarios. Este almacenamiento en caché también se conoce como memorización.
Veamos cómo funciona. Vamos a
crear un componente con un botón y
un encabezado h3:
return (
<div>
<h3>Text</h3>
<button>click</button>
</div>
);
Y ahora hagamos que al hacer clic
en el encabezado, su color cambie de naranja
a verde y viceversa. Para empezar,
creemos un estado isGreen:
const [isGreen, setIsGreen] = useState(false);
Añadamos en el atributo style del encabezado
una condición para cambiar el color y
agreguemos un controlador de clics:
<h3 onClick={() => setIsGreen(!isGreen)}
style={{ color: isGreen ? 'green' : 'orangered' }}
>Text</h3>
Supongamos que también tenemos algún valor que se incrementará en uno al hacer clic en nuestro botón. Creemos un estado para ello:
const [num, setNum] = useState(0);
Añadamos el manejo del clic en el botón:
<button onClick={() => setNum(num + 1)}>
clicks
</button>
Supongamos también que tenemos una función
square, que devolverá
el cuadrado del valor num. El resultado
de llamar a la función lo escribiremos en una
variable result:
const result = square(num);
function square(num) {
return num * num;
}
Mostremos result en el texto del botón:
<button onClick={() => setNum(num + 1)}>
clicks: {result}
</button>
Como resultado, obtuvimos lo siguiente:
al hacer clic en el botón, cambia el valor
de num, que luego se eleva
al cuadrado, y al hacer clic en el encabezado
cambia el color del mismo.
Nuestro componente es muy pequeño, todo funciona rápido, a pesar de que al hacer clic en el encabezado para cambiar su color, todo el componente se vuelve a renderizar, en consecuencia, también se vuelven a realizar los cálculos vinculados al botón, y esto sucede incluso sin que lo hayamos tocado. Ahora imagina si nuestros cálculos fueran pesados y todo se recalculara cada vez.
Hagamos nuestra función un poco más pesada, ahora "pensará" un poco más. De esta manera simularemos cálculos largos:
function square(num) {
let startTime = performance.now();
while (performance.now() - startTime < 500) {
// Simplemente no hacer nada ...
}
return num * num;
}
Ahora haz clic en el encabezado. Resulta
que, debido al largo tiempo de trabajo de la función
square (¡y no estamos tocando el botón!)
¡tenemos que esperar una eternidad para que
el encabezado cambie de color!
¡Es aquí donde el hook
useMemo viene en nuestra ayuda. Para ello, necesitamos pasar
como primer parámetro una función que calcule
el valor que queremos almacenar en caché;
dicha función debe ser pura y no
aceptar ningún parámetro. Y como segundo
parámetro, las dependencias entre corchetes,
en otras palabras, todos los valores
reactivos que participan en el código
de la función. Así, en result
escribiremos ahora una construcción como esta:
const result = useMemo(() => square(num), [num]);
Hagamos clic nuevamente en el encabezado. Ahora,
si no tocamos el botón con los cálculos
y, por lo tanto, no cambiamos el valor del estado
num, entonces nada se recalcula,
y React muestra el valor almacenado en caché
en el botón, por lo que nuestro encabezado
cambia de color rápidamente.
Crea un componente App, coloca
en él un párrafo. Crea un estado text
con un valor inicial 'react',
que el valor del estado se muestre
como texto del párrafo. Que al hacer clic
en el párrafo, se añada al final del texto
un signo de exclamación.
Crea otro estado num, con
un valor inicial de 0. Coloca en
App otro párrafo. Haz que
al hacer clic en él, num
se incremente en 1.
Y ahora añade en App la función
triple, que toma como
parámetro num y
devuelve su valor triplicado.
Guarda el resultado de llamar a la función
en la variable result. Muestra
result como texto del segundo
párrafo. Haz clic sucesivamente en los párrafos,
observa lo lento que se añaden los
signos de exclamación.
Corrige la situación, envolviendo la función lenta
triple en useMemo.