style="display:inline-block;width:728px;height:90px"
data-ad-client="ca-pub-5164839828746352"
data-ad-slot="7563230308">

Rendering por todos lados

Si creaste el contador con Hooks que revisamos con anterioridad, te habras dado cuenta que el contador se incrementa cada segundo, pero no usamos un interval estamos usando setTimeout; esto sucede porque estamos inicializando el setTimeout cada vez que renderizamos el componente y en React esto sucede cada vez que actualizas el estado de un componente, pero si tienes mas de 100000 componentes hijos (tal vez con un poco menos), notaras que empiezas a tener performance issues, antes de hooks la unica forma de solucionarlo es usar uno de las funciones del ciclo de vida de React shouldComponentUpdate pero eso nos obliga a que ese componente sea una Clase (y no queremos clases con Hooks, de hecho no queremos clases del todo :P, OOP is evil).

Para solucionar este posible problema, desde la version 16.6 de React tenemos React.memo que nos ayuda a mostar una version memoizada del componente que queremos, reduciendo drasticamente el numero de repintados en los hijos.

Codigo

Ahora veremos un ejemplo de contador usando React.memo

import React, { useState } from 'react';
import ReactDOM from 'react-dom';

const Child = React.memo(props => {
  console.log(props.text)
  return <div>{props.text}</div>
});

const Hello = props => {
  const [count, setCount] = useState(0);

  let text = 'count 0';

  setTimeout(() => setCount(count+1), 1000);

  text = count % 10 === 0 ? `count ${count}` : text;

  return (
    <React.Fragment>
      <h1>Hello, {count}</h1>
      <Child text={text} />
    </React.Fragment>
  );
};

ReactDOM.render(<Hello text="Javamexico"/>, document.getElementById('app'));

En este ejemplo estamos usando el mismo contador pero tenemos un hijo que solo hara el renderizado cuando la propiedad text cambia, cuando ejecutas este codigo, (npx parcel index.html) podras ver como el contado cambia cada segundo, pero el texto del hijo solo cambia cada 10 segundos y luego vuelve a ser 0. Para comprobar que solo hace un re-render, puedes ver que estoy imprimiendo en consola cada vez que se ejecuta el render del componente hijo. Que igual sucede la primera vez, luego cada 10 segundos y cuando vuelve a cambiar a "count 0"; si quitas React.memo() de Child veras que en la consola sale varias veces "count 0"

Con memo

memo.js:5 count 0
memo.js:5 count 10
memo.js:5 count 0
memo.js:5 count 20
memo.js:5 count 0
memo.js:5 count 30
memo.js:5 count 0

Sin memo

...
memo.js:5 count 0
memo.js:5 count 0
memo.js:5 count 0
memo.js:5 count 10
memo.js:5 count 0
memo.js:5 count 0
memo.js:5 count 0
memo.js:5 count 0
memo.js:5 count 0
memo.js:5 count 0
memo.js:5 count 0
memo.js:5 count 0
memo.js:5 count 0
memo.js:5 count 20
...

Implicaciones

Recuerda que React.memo usa rendering memoizado, por lo que implica mayores consumos de memoria (no mucho pero vale la pena hacer mediciones en aplicaciones grandes 10 - 30 containers con 100 componentes por container por darnos una idea), ademas es muy importante que React.memo no garantiza un unico pintado por actualizacion de propiedades, solo optimiza el numero de repintados. Esto es muy importante no pongas logica que depende de un solo repintado y esperes que React.memo se haga cargo de tu trabajo.

de la pagina de React:

This method only exists as a performance optimization. Do not rely on it to “prevent” a render, as this can lead to bugs.

Se prudente con el uso de React.memo no es necesario ponerlo en todos los componentes hijos, nada es mejor que realizar mediciones de performance para saber donde lo necesitas una buena idea es usarlos en componentes Container y no tanto en componentes Stateless.

style="display:inline-block;width:728px;height:90px"
data-ad-client="ca-pub-5164839828746352"
data-ad-slot="7563230308">