React functional stateless component, PureComponent, Component; ¿cuáles son las diferencias y cuándo debemos usar qué?


Llegó a saber que de React v15.3.0, tenemos una nueva clase base llamada PureComponent para extender con PureRenderMixin incorporado. Lo que entiendo es que, bajo el capó, esto emplea una comparación superficial de accesorios dentro de shouldComponentUpdate.

Ahora tenemos 3 formas de definir un componente React:

  1. Componente funcional sin estado que no extiende ninguna clase
  2. Un componente que extiende PureComponent clase
  3. Un componente normal que se extiende Component clase

Hace algún tiempo solíamos llamar componentes sin estado como Componentes Puros, o incluso Componentes Tontos. Parece que toda la definición de la palabra "puro" ha cambiado ahora en React.

Aunque entiendo las diferencias básicas entre estos tres, todavía no estoy seguro cuándo elegir qué. También, ¿cuáles son los impactos en el desempeño y las compensaciones de cada uno?


Actualización :

Estas son las preguntas que espero obtener clarified:

  • ¿Debo elegir definir mis componentes simples como funcionales (en aras de la simplicidad) o extender la clase PureComponent (en aras del rendimiento)?
  • Es el aumento de rendimiento que obtengo una compensación real por el ¿simplicidad que perdí?
  • ¿Alguna vez necesitaría extender la clase normal Component cuando siempre puedo usar PureComponent para un mejor rendimiento?
Author: free-soul, 2016-11-20

3 answers

¿Cómo decide, cómo elige entre estos tres basados en el propósito/tamaño/accesorios/comportamiento de nuestros componentes?

Extendiéndose desde React.PureComponent o desde React.Component con un método personalizado shouldComponentUpdate tienen implicaciones de rendimiento. El uso de componentes funcionales sin estado es una opción "arquitectónica" y no tiene ningún beneficio de rendimiento desde el primer momento (todavía).

  • Para componentes simples y solo de presentación que necesitan ser reutilizados fácilmente, prefiera stateless functional componente. De esta manera, está seguro de que están desacoplados de la lógica real de la aplicación, que son fáciles de probar y que no tienen efectos secundarios inesperados. La excepción es si por alguna razón tiene muchos de ellos o si realmente necesita optimizar su método de renderizado (ya que no puede definir shouldComponentUpdate para un componente funcional sin estado).

  • Extend PureComponent si sabe que su salida depende de props/state simples ("simple" significa que no hay estructuras de datos anidadas, como PureComponent realiza una comparación superficial) Y necesita/puede obtener algunas mejoras de rendimiento.

  • Extienda Component e implemente su propio shouldComponentUpdate si necesita algunas ganancias de rendimiento al realizar una lógica de comparación personalizada entre los props siguientes/actuales y el estado. Por ejemplo, puede realizar rápidamente una comparación profunda usando lodash # isEqual:

    class MyComponent extends Component {
        shouldComponentUpdate (nextProps, nextState) {
            return !_.isEqual(this.props, nextProps) || !_.isEqual(this.state, nextState);
        }
    }
    

Además, implementar su propio shouldComponentUpdate o extender desde PureComponent son optimizaciones, y como de costumbre debe comenzar a buscar en eso solo si tiene problemas de rendimiento (evite optimizaciones prematuras). Como regla general, siempre trato de hacer estas optimizaciones después de que la aplicación esté en un estado de trabajo, con la mayoría de las características ya implementadas. Es mucho más fácil centrarse en los problemas de rendimiento cuando realmente se interponen en el camino.

Más detalles

Componentes funcionales sin estado:

Estos se definen simplemente usando una función. Ya que no hay estado interno para un componente sin estado, la salida (lo que se renderiza) solo depende de los props dados como entrada a esta función.

Ventajas:

  • La forma más simple posible de definir un componente en React. Si no necesita administrar ningún estado, ¿por qué preocuparse por las clases y la herencia? Una de las principales diferencias entre una función y una clase es que con la función está seguro de que la salida depende solo de la entrada (no de ningún historial de la anterior ejecución).

  • Idealmente, en tu app deberías intentar tener tantos componentes sin estado como sea posible, porque eso normalmente significa que moviste tu lógica fuera de la capa de vista y la moviste a algo como redux, lo que significa que puedes probar tu lógica real sin tener que renderizar nada (mucho más fácil de probar, más reutilizable, etc.).).

Contras:

  • No hay métodos de ciclo de vida. No tienes una manera de definir componentDidMount y otros amigos. Normalmente lo hace dentro de un componente padre más alto en la jerarquía para que pueda convertir todos los hijos en apátridas.

  • No hay forma de controlar manualmente cuando se necesita un re-renderizado, ya que no se puede definir shouldComponentUpdate. Un re-renderizado ocurre cada vez que el componente recibe nuevos props(no hay forma de comparar poco profundo, etc.). En el futuro, React podría optimizar automáticamente los componentes sin estado, por ahora hay algunas bibliotecas que puedes usar. Dado que los componentes sin estado son solo funciones, básicamente es el problema clásico de la "memoización de funciones".

  • No se admiten referencias: https://github.com/facebook/react/issues/4936

Un componente que extiende la clase PureComponent FRENTE a un componente normal que extiende la clase de componente:

React solía tener un PureRenderMixin que se podía adjuntar a una clase definida usando la sintaxis React.createClass. El mixin simplemente definiría un shouldComponentUpdate realizando una comparación superficial entre los siguientes accesorios y el siguiente estado para comprobar si algo ha cambiado. Si nada cambia, entonces no hay necesidad de realizar un re-renderizado.

Si quieres usar la sintaxis ES6, no puedes usar mixins. Así que por conveniencia React introdujo una clase PureComponent de la que puedes heredar en lugar de usar Component. PureComponent simplemente implementa shouldComponentUpdate de la misma manera que el PureRendererMixin. Es principalmente una cosa de conveniencia para que no tenga que implementarlo usted mismo, ya que una comparación superficial entre el estado actual/siguiente y los accesorios es probablemente la más escenario común que puede darle algunas victorias rápidas de rendimiento.

Ejemplo:

class UserAvatar extends Component {
    render() {
       return <div><img src={this.props.imageUrl} /> {{ this.props.username }} </div>
    }
} 

Como puede ver, la salida depende de props.imageUrl y props.username. Si en un componente padre renderizas <UserAvatar username="fabio" imageUrl="http://foo.com/fabio.jpg" /> con las mismas props, React llamaría a render cada vez, incluso si la salida fuera exactamente la misma. Sin embargo, recuerde que React implementa la diferencia de DOM, por lo que el DOM no se actualizaría realmente. Aún así, realizar la diferencia dom puede ser costoso, por lo que en este escenario sería un desperdicio.

Si el componente UserAvatar se extiende PureComponent en su lugar, se realiza una comparación superficial. Y debido a que props y nextProps son lo mismo, render no se llamará en absoluto.

Notas sobre la definición de "puro" en React:

En general, una "función pura" es una función que evalúa siempre el mismo resultado dada la misma entrada. La salida (para React, eso es lo que devuelve el método render) no depende de ningún historial/estado y no tiene ningún efectos secundarios (operaciones que cambian el "mundo" fuera de la función).

En React, los componentes sin estado no son necesariamente componentes puros de acuerdo con la definición anterior si llamas a "sin estado" un componente que nunca llama a this.setState y que no usa this.state.

De hecho, en un PureComponent, todavía puede realizar efectos secundarios durante los métodos de ciclo de vida. Por ejemplo, podría enviar una solicitud ajax dentro de componentDidMount o podría realizar algún cálculo DOM para ajustar dinámicamente el altura de un div dentro de render.

La definición de "Componentes tontos" tiene un significado más "práctico" (al menos en mi entendimiento): a un componente tonto "se le dice" qué hacer por un componente padre a través de props, y no sabe cómo hacer las cosas, pero usa devoluciones de llamada de props en su lugar.

Ejemplo de un "smart" AvatarComponent:

class AvatarComponent extends Component {
    expandAvatar () {
        this.setState({ loading: true });
        sendAjaxRequest(...).then(() => {
            this.setState({ loading: false });
        });
    }        

    render () {
        <div onClick={this.expandAvatar}>
            <img src={this.props.username} />
        </div>
    }
}

Ejemplo de un "mudo" AvatarComponent:

class AvatarComponent extends Component {
    render () {
        <div onClick={this.props.onExpandAvatar}>
            {this.props.loading && <div className="spinner" />}
            <img src={this.props.username} />
        </div>
    }
}

Al final diría que "tonto"," sin estado "y" puro " son conceptos muy diferentes que a veces pueden superposición, pero no necesariamente, dependiendo principalmente de su caso de uso.

 240
Author: fabio.sussetto,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-06-28 19:29:16

No soy un genio sobre react, pero desde mi punto de vista podemos usar cada componente en las siguientes situaciones

  1. Stateless component { estos son los componentes que no tienen ciclo de vida, por lo que esos componentes deben usarse en la representación del elemento repetido del componente padre, como la representación de la lista de texto que solo muestra la información y no tiene ninguna acción que realizar.

  2. Componente Puro -- estos son los elementos que han ciclo de vida y siempre devolverán el mismo resultado cuando se da un conjunto específico de accesorios. Esos componentes se pueden usar cuando se muestra una lista de resultados o datos de un objeto específico que no tiene elementos secundarios complejos y se utilizan para realizar operaciones que solo afectan a sí mismos. tal lista de visualización de tarjetas de usuario o lista de tarjetas de productos (información básica del producto) y la única acción que el usuario puede realizar es hacer clic para ver la página de detalles o agregar al carrito.

  3. Componentes Normales o Complejo Components { Usé el término componente complejo porque esos son generalmente los componentes de nivel de página y consiste en muchos componentes secundarios y ya que cada uno de los hijos puede comportarse de su propia manera única, por lo que no puede estar 100% seguro de que rendirá el mismo resultado en un estado dado. Como he dicho, por lo general, estos deben usarse como componentes contenedores

 19
Author: abhirathore2006,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-02-14 18:28:15

Aquí está mi opinión sobre PureComponent y cuando deberías usarlo (y cuando no deberías): Qué es React.PureComponent y cuándo usarlo

 -1
Author: Sergey Stadnik,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-09-24 23:43:37