Memorizar componentes a través de React.memo en React.js

Inicioreact jsReact memo
Memorizar componentes a través de React.memo en React.js

by Juan Carlos García

3-Mzo-2023

(3)

Suscribirme al canal:

Hola viajero web ¿Qué te ha parecido este curso? Y si es tu primero vez en EWebik, te invito a revisar este curso gratuito de React.js para que comprendas este post a la perfección, ya que, hoy veremos el HOC React.memo, con el cual, podrás mejorar el rendimiento de tus aplicaciones web.

No obstante, debes ser muy cuidadoso en utilizar este tipo de elementos, ya que, quizá solo te hagan escribir más código y no agregue una mejora significativa en tus aplicaciones.

¡No te puedes perder las nuevas clases 🧐!

React JS

React JS

React.js: El mejor curso gratuito de React.js desde cero.

¿Que es React JSX?

¿Que es React JSX?

Guía para principiantes de React JSX: ¿Qué es React JSX? Introducción a React JSX

Componentes y propiedades

Componentes y propiedades

Components and Props React.js, Manejo de propiedades y componentes en React

State y Ciclo de vida en React

State y Ciclo de vida en React

State And Lifecycle: Comprendiendo el State y Ciclo de vida de los componentes en React.js

Refs React

Refs React

¿Qué son las React Refs y para que sirven? Uso de las Refs y manejo del DOM en React.js

Listas y condiciones en React

Listas y condiciones en React

Keys and List: ¿Cómo manejar las listas y condicionales en React JS?

Formularios en React

Formularios en React

Formularios en React: ¿Cómo manejar los formularios en React.js con input controlados y no controlados?

React develepor tools

React develepor tools

React Developer Tools: ¿Cómo analizar el comportamiento y estado de nuestros componentes en React.js?

API Context

API Context

API Context en React: ¿Cómo comunicar componentes mediante API Context en React.js?

Higher Order Component

Higher Order Component

HOC en React.js: ¿Cómo utilizar los High Order Component (HOC) ?

Children en React JS

Children en React JS

Children en React.js: Manejo avanzado de Children en React.js, composición de componentes.

PropTypes en React

PropTypes en React

PropType en React.js: ¿Cómo validar datos a través de PropType en React.js?

Hooks en React JS

Hooks en React JS

Master de Hooks en React JS: ¿Qué es un Hook en React.js? Tipos, funcionamiento y características.

Hook useState

Hook useState

useState: ¿Cómo utilizar el Hook useState en React.js?

Hook useEffect

Hook useEffect

Hook useEffect: ¿Qué es el Hook useEffect? ¿Cómo utilizarlo correctamente y qué reglas seguir?

Hook useContext

Hook useContext

¿Cómo utilizar el Hook useContext? Comunicación de componentes funcionales

Hook useReducer

Hook useReducer

¿Cómo utilizar el Hook useReducer en React.js?

React memo

React memo

Memorizar componentes a través de React.memo en React.js

Hook useCallback

Hook useCallback

Utilizando los Hooks useCallback y useMemo en React.js

🧐 Autoevaluación: React memo

¿Qué es React.memo() ?

¿Cuándo usar React.Memo?

¿Cuándo NO utilizar React.Memo()?

¿Qué aprenderás de React.memo?

  • Aprenderás a memorizar componentes a través de React.memo
  • Comprenderás por qué, tu componente se vuelve a montar cuando hay una actualización de propiedades.
  • Entenderás que debes hacer para forzar el render de tus componentes cuando tienes propiedades de primer y segundo nivel.
  • Aprenderás a realizar una diferenciación manual de las propiedades en un componente, para asegurar que este se actualice, si y solo si, hay un cambio en las propiedades.

Repositorio

  • Descarga el código de esta clase aquí.
  • O clona el repositorio y salta a la rama "react-memo"

 

git clone https://github.com/EWebik/react-js.git
git checkout react-memo

 

¿Qué es React.memo() ?

React.memo() es un HOC que permite memorizar un componente en memoria, esto quiere decir:

  • React toma nuestro componente que envolvemos con React.memo, lo renderiza y lo almacena en memoria.
  • Ahora, antes del siguiente render de nuestro componente memorizado, React evaluará si las propiedades han cambiado, si existe un cambio, lo volverá a renderizar y grabar en memoria, de lo contrario, utilizará el que esta en la memoria.

Lo anterior tiene ventajas y desventajas, tal y como lo veremos a continuación.

 

¿Cuando usar React.memo() ?

Existen algunos casos donde utilizar este HOC es muy útil, por ejemplo:

  • Si tu componente siempre regresa la misma salida.
  • Cuando las propiedades de tu componente nunca cambian.
  • Si tu componente debe renderizar una gran cantidad de elementos, por ejemplo: una lista.

 

¿Cuándo no utilizar React.memo() ?

Para responder a esta pregunta quizá necesitaría más puntos que en el apartado anterior, así que, lo resumiré en una simple frase:

Evita utilizar React.memo() cuando no te sea posible cuantificar la mejora que se tiene en rendimiento.

 

¿Cómo implementar React.memo() ?

Antes de pasar al ejemplo, creo que debes conocer como declararlo y como esta compuesto este HOC.

//Declaración
React.memo(<Component />, ()=>{})

 

  • Bien, para utilizar este HOC podemos acceder a el, a través, de la notación de punto React.memo.
  • Y como todo HOC, nos permite envolver un componente, el cual, lo pasamos como primer parámetro.
  • Como segundo parámetro recibe una función, con la cual, podemos analizar las propiedades y, decidir, si el componente debe volver a renderizarse o no.

Para que te quede más claro de como utilizar este HOC, vamos hacer un ejemplo donde:

  • Veremos como memorizar un componente, con propiedades de primer nivel
  • Y como memorizar un componente con propiedades de segundo nivel.

Recuerda que si tienes dudas, te invito a ver el vídeo, suscríbete a mi canal y mándame por correo tus dudas.

Ejemplo React.memo()

Para ejemplificar el comportamiento de este HOC, lo que vamos hacer es lo siguiente.

Ejemplo de como utilizar React.memo()

En la imagen anterior podemos observar tres componentes:

  • El primer componente no estará memorizado.
  • El segundo componente estará memorizado.
  • Y el tercer componente estará memorizado, pero, las propiedades que se le pasan son de segundo nivel, por lo que, tendremos que hacer una diferenciación manual de las propiedades para indicar cuando debe volver a renderizarse.

 

1 Componente no memorizado

Bien, primero desarrollemos el componente no renderizado, recuerda ver el vídeo para que comprendas mejor el ejemplo.

//Componente no memorizado

const Counter = (props)=>{
  const {counter, title}=props;
  return(
    <div className="hijo">
      <h2>{title}</h2>
      <h3>{"Cuenta: " + counter}</h3>
      <p>{"Último render: " + new Date().getMilliseconds()}</p>
    </div>
  )
}

 

  • Counter, es un componente que mostrará la cuenta que se genera desde el componente padre.
  • A este componente se le pasan las propiedades title y counter.
  • En el marcado podemos observar que agregamos  <p>{"Último render: " + new Date().getMilliseconds()}</p> , el cual, será un párrafo que sirve de log, con la finalidad de saber si el componente ha vuelto a renderizar.

Hasta este punto no tenemos nada nuevo, tenemos un componente que actualizará siempre que haya un cambio de propiedades o state, tanto en el mismo, como, en su componente padre.

 

2 Componente memorizado con propiedades de primer nivel

//Utilizando React.memo

const CounterMemo = React.memo(
  (props)=>{
    return(
      <Counter {...props} />
    )
});

 

  • El componente <CounterMemo />, lo único que hace es envolver al componente <Counter /> y le pasa todas las propiedades.
  • Con este simple código, ya hemos memorizado nuestro primer componente, el cual, no volverá a renderizar a menos que las propiedades cambien.

 

2 Componente memorizado con propiedades de segundo nivel

Quizá el termino segundo nivel se escuche raro, pero, es la forma en la que nombro a las propiedades de un objeto, como lo es un JSON, ya que, el JSON por si mismo, sería de primer nivel y sus propiedades el segundo nivel y, así sucesivamente según las anidaciones que tenga el objeto.

const CounterMemo1 = React.memo(
  (props)=>{
    const {data} = props;
    return(
      <Counter 
        title={data.title}
        counter={data.counter} />
    )
});

 

  • <CounterMemo1 /> Este componente esta memorizado, no obstante, las propiedades que se le pasan están contenidas en un JSON de nombre data.
  • Para este caso, si hay un cambio en el componente padre, <CounterMemo1 /> se volverá a renderizar, aun cuando, el JSON data no haya cambiado.

Lo anterior pareciera un error, sin embargo, no lo es, esto se debe a que React.memo(), solo evalúa las propiedades primitivas o de primer nivel, esta es la razón, por la cual, <CounterMemo1 /> vuelve a renderizar, aún cuando, sus propiedades no hayan cambiado.

Diferenciación manual de propiedades en React.memo()

Hay una solución para este caso y, es evaluar las propiedades que recibimos en el JSON data manualmente, para ello vamos a utilizar el segundo argumento de React.memo(), donde:

  • Si las propiedades en el JSON data cambiaron, volveremos a renderizar el componente.
  • Pero, si las propiedades no cambian, no se volverá a renderizar.

 

//Diferenciación manual de propiedades

const CounterMemo1 = React.memo(
  (props)=>{
    const {data} = props;
    return(
      <Counter 
        title={data.title}
        counter={data.counter} />
    )
},(prevProps, nextProps)=>{
  //Si retornamos true:  No se renderiza
  //Si retornamos false: Si se renderiza
  return (
    prevProps.data.title === nextProps.data.title &&
    prevProps.data.counter === nextProps.data.counter
  )
});

 

  • React.memo() como segundo argumento regresa una función con los parámetros de:
    • Propiedades previas (prevProps)
    • Propiedades siguientes (nextProps)
  • Esta función regresa un booleano, donde:
    • Si es true o verdadero, el componente no volverá a renderizar.
    • Si es false o falso, el componente volverá a renderizarse.

Y es precisamente en esta función donde vamos a comparar las props previas con las siguientes, para corroborar si son distintas y, si son distintas regresamos un false, para volver a renderizar <CounterMemo1 />.

(prevProps, nextProps)=>{
  //Si retornamos true:  No se renderiza
  //Si retornamos false: Si se renderiza
  return (
    prevProps.data.title === nextProps.data.title &&
    prevProps.data.counter === nextProps.data.counter
  )
}

 

3 Creando el componente padre

Ahora veamos como queda el componente padre donde mandamos llamar a cada Counter.

const Component = ()=>{
  const [counter1, setCounter1] = useState(0);
  const [counter2, setCounter2] = useState(0);
  const [counter3, setCounter3] = useState(0);

  useEffect(()=>{
    setTimeout(() => {
      setCounter1(counter1 + 1);
    }, 100);
  },[counter1]);

  useEffect(()=>{
    setTimeout(() => {
      setCounter2(counter2 + 1);
    }, 4000);
  },[counter2]);

  useEffect(()=>{
    setTimeout(() => {
      setCounter3(counter3 + 1);
    }, 500);
  },[counter3]);

  return(
    <div className="padre">
      <h1>{"EWebik mejorando el rendimiento con React.memo()"}</h1>
      <div className="hijos">
        <Counter
          title={"No memorizado"}
          counter={counter1}/>

        <CounterMemo
          title={"Memorizado"}
          counter={counter2}/>

        <CounterMemo1
          data={{
            title:"Memorizado 2do nivel",
            counter:counter3
          }} />
      </div>
    </div>
  )
}

 

  • Lo primero que hacemos es agregar tres variables de estado a través del Hook useState, counter1, counter2 y counter3.
  • Vamos a crear tres tareas a través del Hook useEffect, donde agregaremos un setTimeOut, el cual, actualizará su counter correspondiente.
  • En el marcado agregaremos los componentes:
    • <Counter />
    • <CounterMemo />
    • <CounterMemo1 />
  • Cada componente actualizará, si y solo si, sus propiedades cambian.

 

Excelente, en este punto la aplicación esta completa, cada componente renderiza correctamente, si tienes dudas, por favor, mira el vídeo para que veas todo en acción, ya que, en el vídeo vamos desarrollando cada componente paso a paso.

Esto a sido todo por el momento, espero que te haya gustado este post y que hayas aprendido mucho sobre React.memo, te recomiendo hagas más ejemplos, para que vayas practicando, nos vemos en el siguiente post.

🧐 Autoevaluación: React memo

¿Qué es React.memo() ?

¿Cuándo usar React.Memo?

¿Cuándo NO utilizar React.Memo()?

Juan Carlos

Juan Carlos García

Desarrollador de software / SEO

Durante años he desarrollado plataformas dedicadas al rastreo satelital y varios sitios web que se encuentran en la primera página de Google, y hoy quiero compartir contigo lo que se en tecnologías como: Node JS, PHP, C# y Bases de datos.

Si quieres apoyarme sígueme en mis redes sociales y suscríbete a mi canal de YouTube.

EWebik

Diseño de páginas web y aplicaciones moviles.

© 2024 EWebik