¿Cuál es la diferencia entre "super ()" y "super (props)" en React cuando se usan las clases es6?

Respuestas:

710

Solo hay una razón por la que hay que pasar propsa super():

Cuando quieras acceder this.propsen constructor.

Paso:

class MyComponent extends React.Component {    
    constructor(props) {
        super(props)

        console.log(this.props)
        // -> { icon: 'home', … }
    }
}

No pasa:

class MyComponent extends React.Component {    
    constructor(props) {
        super()

        console.log(this.props)
        // -> undefined

        // Props parameter is still available
        console.log(props)
        // -> { icon: 'home', … }
    }

    render() {
        // No difference outside constructor
        console.log(this.props)
        // -> { icon: 'home', … }
    }
}

Tenga en cuenta que pasa o no pasa propsa supertiene ningún efecto sobre los usos posteriores del this.propsexterior constructor. Es decir render, shouldComponentUpdateo los controladores de eventos siempre tienen acceso a él.

Esto se dice explícitamente en la respuesta de Sophie Alpert a una pregunta similar.


La documentación: Estado y ciclo de vida, Agregar estado local a una clase, punto 2, recomienda:

Los componentes de clase siempre deben llamar al constructor base con props.

Sin embargo, no se proporciona ninguna razón. Podemos especular que es por subclases o por compatibilidad futura.

(Gracias @MattBrowne por el enlace)

Robin Pokorny
fuente
16
Creo que tienes razón, a pesar de que las otras respuestas obtienen más votos. this.propses a undefinedmenos que se pase a super(). De cualquier manera, no afecta la representación posterior o la disponibilidad de this.propsla render()función.
Micros
3
@Rotareti, no, en realidad el resto de la clase no depende de esta construcción, ese es el punto. El componente recibe apoyos de una manera diferente que por parámetro de constructor. Y como pasa los accesorios iniciales a super, tiene referencia a ellos en el constructor.
Robin Pokorny
77
De acuerdo con la documentación de React, siempre debe pasar propsa super(): facebook.github.io/react/docs/… . No estoy seguro de por qué, ya que como señala this.propses accesible en otros métodos de cualquier manera ... ¿tal vez están recomendando esto para compatibilidad futura en caso de que futuras versiones de React quieran hacer algo propsen el constructor?
Matt Browne
23
Tal vez estoy abriendo una lata de gusanos aquí, pero ¿por qué nunca pasar propsa supercuando, como usted ha señalado, el propsparámetro está ahí disponible para nosotros para usar dentro del constructor , y this.propsfunciona en todas partes? ¿Hay algún beneficio en usar this.propssolo props? ¿Es una mala práctica desestructurar propsen el constructor? Creo que todavía estoy a falta de ver un caso en el que te vez tiene que pasar propsa super, pero estoy dispuesto a apostar que es sólo mi ignorancia, ja.
indiesquidge
99
Si lo usa super(props), puede llamar a métodos que se usan this.props desde el constructor , como this.doStuffUsingThisDotProps(), sin tener que pasar el parámetro props a esos métodos / funciones. Acabo de escribir un constructor que hace esto, que aparentemente requeriría que lo use super(props)primero, de acuerdo con las respuestas a esta pregunta.
Victor Zamanian
54

En este ejemplo, está extendiendo la React.Componentclase y, según la especificación ES2015, un constructor de clase hijo no puede usar thishasta que super()se haya llamado; Además, los constructores de clase ES2015 tienen que llamar super()si son subclases.

class MyComponent extends React.Component {
  constructor() {
    console.log(this); // Reference Error
  }

  render() {
    return <div>Hello {this.props.name}</div>;
  }
}

Por el contrario:

class MyComponent extends React.Component {
  constructor() {
    super();
    console.log(this); // this logged to console
  }

  render() {
    return <div>Hello {this.props.name}</div>;
  }
}

Más detalles según esta excelente respuesta de desbordamiento de pila

Puede ver ejemplos de componentes creados al extender la React.Componentclase que no llama, super()pero notará que estos no tienen un constructor, por lo que no es necesario.

class MyOtherComponent extends React.Component {
  render() {
    return <div>Hi {this.props.name}</div>;
  }
}

Un punto de confusión que he visto de algunos desarrolladores con los que he hablado es que los componentes que no tienen constructory, por lo tanto, no llaman a super()ninguna parte, todavía están this.propsdisponibles en el render()método. Recuerde que esta regla y esta necesidad de crear una thisunión por el constructorsólo se aplica al constructor.

Dave
fuente
15
Muchas gracias por su respuesta, pero no responde a mi pregunta original (diferencia entre super()y super(props)).
Misha Moroshko
46

Cuando pasas propsa super, los accesorios se asignan this. Eche un vistazo al siguiente escenario:

constructor(props) {
    super();
    console.log(this.props) //undefined
}

Como siempre que lo haces:

constructor(props) {
    super(props);
    console.log(this.props) //props will get logged.
}
Nahush Farkande
fuente
La mejor respuesta en la lista.
Basavaraj Hadimani
Esta respuesta es la mitad correcta. Este ejemplo es solo para el método del constructor. Por ejemplo, incluso si no escribe super (props), this.props bajo el método de renderizado todavía se asignará y estará disponible. La única razón mencionada anteriormente es cuando se usa this.props en el constructor.
Ofear
12

Según el código fuente

function ReactComponent(props, context) {
  this.props = props;
  this.context = context;
}

debes pasar propscada vez que tengas accesorios y no los pongas this.propsmanualmente.

zerkms
fuente
1
Todavía no estoy claro en esto. Si observa estos dos componentes , puede ver una llamada super(props)y la otra no. Pero sus consumidores ambos establecen accesorios. ¿Cuál es la diferencia?
Kyeotic
¿Esto significa eso this.props = propsy super(props)son lo mismo?
reectrix
1
Esto no es verdad. ReactElement en realidad se establece this.propsdesde el 'exterior', independientemente de lo que se haga en el constructor.
Robin Pokorny
11

Dan Abramov escribió un artículo sobre este tema:

¿Por qué escribimos super (accesorios)?

Y lo esencial es que es útil tener el hábito de pasarlo para evitar este escenario, que honestamente, no veo que sea poco probable que suceda:

// Inside React
class Component {
  constructor(props) {
    this.props = props;
    // ...
  }
}

// Inside your code
class Button extends React.Component {
  constructor(props) {
    super(); // 😬 We forgot to pass props
    console.log(props);      // ✅ {}
    console.log(this.props); // 😬 undefined 
  }
  // ...
}
Alfonso Pérez
fuente
7

Al implementar la constructor()función dentro de un componente React, super()es un requisito. Tenga en cuenta que su MyComponentcomponente está ampliando o tomando prestada la funcionalidad de la React.Componentclase base.

Esta clase base tiene una constructor()función propia que tiene un código dentro de ella, para configurar nuestro componente React para nosotros.

Cuando definimos una constructor()función dentro de nuestra MyComponentclase, esencialmente estamos anulando o reemplazando la constructor()función que está dentro de la React.Componentclase, pero aún debemos asegurarnos de que todavía se invoque todo el código de configuración dentro de esta constructor()función.

Así que para asegurarse de que la React.Component's constructor()función se llama, que llamamos super(props). super(props)es una referencia a la constructor()función de los padres , eso es todo.

Tenemos que agregar super(props)cada vez que definimos una constructor()función dentro de un componente basado en clases.

Si no lo hacemos, veremos un error que dice que tenemos que llamar super(props).

La razón completa para definir esta constructor()función es inicializar nuestro objeto de estado.

Entonces, para inicializar nuestro objeto de estado, debajo de la súper llamada voy a escribir:

class App extends React.Component {
  constructor(props) {
      super(props);

      this.state = {};
   }

  // React says we have to define render()
  render() {
    return <div>Hello world</div>;
  }
};

Así que hemos definido nuestro constructor()método, inicializado nuestro objeto de estado creando un objeto JavaScript, asignándole una propiedad o un par clave / valor, asignándole el resultado de eso this.state. Ahora, por supuesto, esto es solo un ejemplo aquí, así que realmente no he asignado un par clave / valor al objeto de estado, es solo un objeto vacío.

Daniel
fuente
4

Aquí está el violín que hice: jsfiddle.net . Muestra que los accesorios no están asignados en el constructor por defecto. Según tengo entendido, están asignados en el método React.createElement. Por lo tanto, super(props)debería ser llamado sólo cuando assings constructor de la superclase manualmente propsa this.props. Si solo extiende la React.Componentllamada super(props), no hará nada con los accesorios. Tal vez se cambiará en las próximas versiones de React.

beshanoe
fuente
3

Aquí no conseguiremos esto en el constructor, por lo que volverá indefinido, pero podremos recuperar esto fuera de la función del constructor

class MyComponent extends React.Component {
  constructor() {
    console.log(this); // Reference Error i.e return undefined
  }

  render() {
    return <div>Hello {this.props.name}</div>;
  }
}

Si estamos usando super (), también podemos obtener la variable "this" dentro del constructor

class MyComponent extends React.Component {
  constructor() {
    super();
    console.log(this); // this logged to console
  }

  render() {
    return <div>Hello {this.props.name}</div>;
  }
}

Entonces, cuando estamos usando super (); podremos buscar esto pero this.props no estará definido en el constructor. Pero aparte del constructor, this.props no volverá indefinido.

Si usamos super (props), también podemos usar el valor this.props dentro del constructor

La respuesta de Sophie Alpert

Si desea usar this.props en el constructor, debe pasar los accesorios a super. De lo contrario, no importa porque React establece .props en la instancia desde el exterior inmediatamente después de llamar al constructor.

VIKAS KOHLI
fuente
3

Para la versión de reacción 16.6.3, utilizamos super (props) para inicializar el nombre del elemento de estado : this.props.name

constructor(props){
    super(props);        
}
state = {
  name:this.props.name 
    //otherwise not defined
};
Shubham Kapoor
fuente