Le presentamos una traducci贸n del art铆culo de Chidume Nnamdi, que se public贸 en blog.bitsrc.io. Si desea aprender c贸mo evitar renderizaciones innecesarias y lo 煤tiles que son las nuevas herramientas en React, bienvenido a cat.

El equipo React.js est谩 trabajando duro para hacer que React se ejecute lo m谩s r谩pido posible. Para permitir a los desarrolladores acelerar sus aplicaciones React, se han agregado las siguientes herramientas:
- React. Perezoso y suspenso para carga de componentes retrasada;
- Componente puro
- los ganchos del ciclo de vida debenComponentUpdate (...) {...}.
En este art铆culo, consideraremos, entre otras, otra herramienta de optimizaci贸n agregada en React v16.6 para acelerar las funciones de los componentes:
React.memo .
Consejo: Use
Bit para instalar y compartir componentes React. Use sus componentes para crear nuevas aplicaciones y compartirlas con el equipo para acelerar las cosas. 隆Pru茅balo!

Render extra
En React, cada componente corresponde a una unidad de vista. Los componentes tambi茅n tienen estados. Cuando el valor del estado cambia debido a las acciones del usuario, el componente se da cuenta de que se necesita volver a dibujar. El componente Reaccionar se puede volver a dibujar cualquier cantidad de veces. En algunos casos, esto es necesario, pero la mayor铆a de las veces puede prescindir de un renderizador, especialmente porque ralentiza enormemente la aplicaci贸n.
Considere el siguiente componente:
import React from 'react'; class TestC extends React.Component { constructor(props) { super(props); this.state = { count: 0 } } componentWillUpdate(nextProps, nextState) { console.log('componentWillUpdate') } componentDidUpdate(prevProps, prevState) { console.log('componentDidUpdate') } render() { return ( <div > {this.state.count} <button onClick={()=>this.setState({count: 1})}>Click Me</button> </div> ); } } export default TestC;
El valor inicial del estado {count: 0} es 0. Si hace clic en el bot贸n Click me, el estado del conteo se convertir谩 en 1. En nuestra pantalla, 0 tambi茅n cambiar谩 a 1. Pero si hacemos clic nuevamente en el bot贸n, comienzan los problemas: el componente no se debe volver a dibujar, porque La condici贸n no ha cambiado. El valor del contador "a" es 1, el nuevo valor tambi茅n es uno, lo que significa que no hay necesidad de actualizar el DOM.
Para ver la actualizaci贸n de nuestro TestC, en el que se establece el mismo estado dos veces, agregu茅 dos m茅todos de ciclo de vida. React inicia el ciclo componentWillUpdate cuando el componente se actualiza / redibuja debido a un cambio de estado. El ciclo componentdidUpdate React comienza cuando un componente se procesa correctamente.
Si lanzamos el componente en el navegador e intentamos hacer clic en el bot贸n Hacer clic varias veces, obtenemos el siguiente resultado:

La repetici贸n de la entrada componentWillUpdate en nuestra consola indica que el componente se vuelve a dibujar incluso cuando el estado no cambia. Este es un render extra.
Componente puro / shouldComponentUpdate
El enlace del ciclo de vida shouldComponentUpdate ayudar谩 a evitar la representaci贸n innecesaria en los componentes React.
React inicia el m茅todo
shouldComponentUpdate al comienzo de la representaci贸n del componente y recibe una luz verde de este m茅todo para continuar el proceso o una se帽al de que el proceso est谩
inhibido .
Deje que deber铆a deber铆a ser nuestro UpdateComponentUpdate as铆:
shouldComponentUpdate(nextProps, nextState) { return true }
nextProps
: el siguiente valor de props
que recibir谩 el componente;nextState
: el siguiente valor de state
que recibir谩 el componente.
Entonces permitimos que React represente el componente porque el valor de retorno es
true
.
Supongamos que escribimos lo siguiente:
shouldComponentUpdate(nextProps, nextState) { return false }
En este caso, prohibimos que React procese el componente, porque
false
devuelve
false
.
De lo anterior se deduce que para renderizar el componente necesitamos devolver
true
. Ahora podemos reescribir el componente TestC de la siguiente manera:
import React from 'react'; class TestC extends React.Component { constructor(props) { super(props); this.state = { count: 0 } } componentWillUpdate(nextProps, nextState) { console.log('componentWillUpdate') } componentDidUpdate(prevProps, prevState) { console.log('componentDidUpdate') } shouldComponentUpdate(nextProps, nextState) { if (this.state.count === nextState.count) { return false } return true } render() { return ( <div> { this.state.count } <button onClick = { () => this.setState({ count: 1 }) }> Click Me </button> </div> ); } } export default TestC;
Agregamos un enlace shouldComponentUpdate al componente TestC. Ahora el valor de
count
en el objeto de estado actual
this.state.count
compara con el valor de
count
en el siguiente objeto de estado
nextState.count
. Si son iguales
===
, no se vuelve a dibujar y
false
devuelve
false
. Si no son iguales,
true
devuelve
true
y se inicia un renderizador para mostrar el nuevo valor.
Si probamos el c贸digo en un navegador, veremos un resultado familiar:

Pero al hacer clic en el bot贸n
Click Me
clic varias veces, todo lo que vemos es lo siguiente (隆se muestra solo una vez!):
componentWillUpdate
componentDidUpdate

Puede cambiar el estado del componente TestC en la pesta帽a React DevTools. Haga clic en la pesta帽a Reaccionar, seleccione TestC a la derecha y ver谩 el valor del estado del contador:

Este valor puede ser cambiado. Haga clic en el texto del contador, escriba 2 y presione Entrar.

El estado del conteo cambiar谩 y en la consola veremos:
componentWillUpdate componentDidUpdate componentWillUpdate componentDidUpdate

El valor anterior era 1 y el nuevo era 2, por lo que era necesario volver a dibujar.
Pasemos al
componente puro .
Pure Component apareci贸 en React en la versi贸n v15.5. Se utiliza para comparar valores predeterminados (
change detection
). Usando
extend React.PureComponent
, no tiene que agregar el m茅todo del ciclo de vida
shouldComponentUpdate
a los componentes: el seguimiento de cambios ocurre por s铆 mismo.
Agregue un PureComponent al componente TestC.
import React from 'react'; class TestC extends React.PureComponent { constructor(props) { super(props); this.state = { count: 0 } } componentWillUpdate(nextProps, nextState) { console.log('componentWillUpdate') } componentDidUpdate(prevProps, prevState) { console.log('componentDidUpdate') } render() { return ( <div> { this.state.count } <button onClick = { () => this.setState({ count: 1 }) }> Click Me </button> </div > ); } } export default TestC;
Como puede ver,
shouldComponentUpdate
en un comentario. Ya no lo necesitamos: todo el trabajo lo realiza
React.PureComponent
.
Al reiniciar el navegador para probar la nueva soluci贸n, y al hacer clic en el bot贸n
Click Me
clic varias veces, obtenemos:


Como puede ver, solo apareci贸 una entrada de
component*Update
en la consola.
Despu茅s de ver c贸mo trabajar en React con redibujar en las clases de componentes de ES6, pasamos a las funciones de los componentes. 驴C贸mo lograr los mismos resultados con ellos?
Componentes de funciones
Ya sabemos c贸mo optimizar el trabajo con clases usando el componente Pure y el
shouldComponentUpdate
ciclo de vida
shouldComponentUpdate
. Nadie argumenta que los componentes de clase son los componentes principales de React, pero puede usar funciones como componentes.
function TestC(props) { return ( <div> I am a functional component </div> ) }
Es importante recordar que los componentes de la funci贸n, a diferencia de los componentes de la clase, no tienen estado (aunque ahora que han
useState
ganchos de
useState
, esto puede discutirse), lo que significa que no podemos configurar su redibujo. Los m茅todos de ciclo de vida que utilizamos al trabajar con clases no est谩n disponibles aqu铆. Si podemos agregar ganchos de ciclo de vida a los componentes de la funci贸n, podemos agregar el m茅todo
shouldComponentUpdate
para decirle a React que se necesita un procesador de funciones. (Quiz谩s el autor cometi贸 un error de hecho en la 煤ltima oraci贸n. - Aprox. Ed.) Y, por supuesto, no podemos usar
extend React.PureComponent
.
Convertimos nuestra clase de componente ES6 TestC en una funci贸n de componente.
import React from 'react'; const TestC = (props) => { console.log(`Rendering TestC :` props) return ( <div> {props.count} </div> ) } export default TestC;
Despu茅s de renderizar en la consola, vemos la entrada
Rendering TestC :5
.

Abra DevTools y haga clic en la pesta帽a Reaccionar. Aqu铆 intentaremos cambiar el valor de las propiedades del componente TestC. Seleccione TestC, y las propiedades del contador con todas las propiedades y valores de TestC se abrir谩n a la derecha. Solo vemos el contador con el valor actual de 5.
Haga clic en el n煤mero 5 para cambiar el valor. En su lugar, aparecer谩 una ventana de entrada.

Si cambiamos el valor num茅rico y presionamos Enter, las propiedades del componente cambiar谩n de acuerdo con el valor que ingresamos. Supongamos que a los 45.

Vaya a la pesta帽a Consola.

El componente TestC se volvi贸 a dibujar porque el valor anterior de 5 cambi贸 al actual - 45. Vuelva a la pesta帽a Reaccionar y cambie el valor a 45, luego regrese a la Consola.

Como puede ver, el componente se vuelve a dibujar, aunque los valores anteriores y nuevos son los mismos. :(
驴C贸mo gestionar un renderizador?
Soluci贸n: React.memo ()
React.memo()
es una nueva caracter铆stica introducida en React v16.6. Su principio de funcionamiento es similar al principio de
React.PureComponent
: ayuda en la gesti贸n del redise帽o de funciones de componentes.
React.memo(...)
para componentes de clase es
React.PureComponent
para componentes de funci贸n.
驴C贸mo trabajar con React.memo (...)?Bastante simple Digamos que tenemos una funci贸n componente.
const Funcomponent = ()=> { return ( <div> Hiya!! I am a Funtional component </div> ) }
Solo necesitamos pasar FuncComponent como argumento para la funci贸n React.memo.
const Funcomponent = ()=> { return ( <div> Hiya!! I am a Funtional component </div> ) } const MemodFuncComponent = React.memo(FunComponent)
React.memo devuelve MemodFuncComponent
purified MemodFuncComponent
. Esto es lo que dibujaremos en el marcado JSX. Cuando las propiedades y el estado de un componente cambian, React compara las propiedades y estados anteriores y actuales del componente. Y solo si no son id茅nticos, la funci贸n componente se vuelve a dibujar.
Aplique esto al componente de funci贸n TestC.
let TestC = (props) => { console.log('Rendering TestC :', props) return ( <div> { props.count } </> ) } TestC = React.memo(TestC);
Abra un navegador y descargue la aplicaci贸n. Abra DevTools y vaya a la pesta帽a Reaccionar. Seleccione
<Memo(TestC)>
.
Si en el bloque de la derecha cambiamos las propiedades del contador a 89, la aplicaci贸n se volver谩 a dibujar.

Si cambiamos el valor al anterior, 89, entonces ...

隆No habr谩 redibujos!
Gloria a reaccionar.memo (...)! :)
Sin usar
React.memo(...)
en nuestro primer ejemplo, la funci贸n del componente TestC se vuelve a dibujar incluso cuando el valor anterior cambia a uno id茅ntico. Ahora, gracias a
React.memo(...)
, podemos evitar la representaci贸n innecesaria de las funciones de los componentes.
Conclusi贸n
- Vamos a repasar la lista?
React.PureComponent
- plata;React.memo(...)
- oro;React.PureComponent
funciona con clases ES6;React.memo(...)
funciona con funciones;React.PureComponent
optimiza el redise帽o de las clases ES6;React.memo(...)
optimiza el redise帽o de la funci贸n;- la optimizaci贸n de funciones es una idea excelente;
React
nunca volver谩 a ser lo mismo.
Si tiene alguna pregunta sobre el art铆culo o cualquier informaci贸n adicional, cambios u objeciones, no dude en escribirme comentarios, correos electr贸nicos o mensajes privados.
Gracias