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

604

¿Cuándo es importante para pasar propsa super(), y por qué?

class MyComponent extends React.Component {
  constructor(props) {
    super(); // or super(props) ?
  }
}
1
786

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

Cuando desee acceder this.propsen constructor.

Paso:

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

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

No pasando:

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 pasar o no pasar propsa nosuper tiene ningún efecto en 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 una respuesta de Sophie Alpert a una pregunta similar.


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

Class components should always call the base constructor with props.

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

(Gracias @MattBrowne por el enlace)

19
  • 20
    Creo que tiene 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 reproducción posterior o la disponibilidad de this.propsen la render()función.
    Micros
    29 de enero de 2016 a las 11:11
  • 3
    @Rotareti, no, en realidad el resto de la clase no depende de esta construcción, ese es el punto. El componente recibe accesorios de una manera diferente a la del parámetro del constructor. Y dado que le pasa los accesorios iniciales a super, tiene una referencia a ellos en el constructor. 17/07/2016 a las 18:42
  • 8
    De acuerdo con la documentación de React, siempre debes 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 lo estén recomendando para compatibilidad futura en caso de que las versiones futuras de React quieran hacer algo propsen el constructor. 1 de ene. De 2017 a las 13:45
  • 28
    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.propsover just 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. 22 de agosto de 2017 a las 4:30
  • 14
    Si lo usa super(props), puede llamar a métodos que 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 haciendo esto, que aparentemente requeriría que lo use super(props)primero, de acuerdo con las respuestas a esta pregunta. 9 de enero de 2018 a las 9:03
sesenta y cinco

En este ejemplo, está ampliando la React.Componentclase y, según la especificación ES2015, un constructor de clases secundarias no puede utilizarlo thishasta que super()se haya llamado; Además, los constructores de clases de 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 tanto, no es necesario.

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

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

1
  • 17
    Muchas gracias por su respuesta, pero no responde a mi pregunta original (diferencia entre super()y super(props)). 6 de diciembre de 2015 a las 7:18
56

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

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

Como siempre cuando lo hagas:

constructor(props) {
    super(props);
    console.log(this.props) //props will get logged.
}
2
  • 1
    La mejor respuesta de la lista. 18 de diciembre de 2018 a las 5:45
  • 1
    Esta respuesta es mitad correcta, este ejemplo es solo para el método constructor. Por ejemplo, incluso si no escribe super (props), this.props en el método de renderización seguirá estando asignado y disponible. La única razón mencionada anteriormente es cuando se usa this.props en el constructor.
    Ofear
    24 feb.20 a las 18:48
17

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

Esta clase base tiene una constructor()función propia que tiene algún código dentro de ella, para configurar nuestro componente React por 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 necesitamos asegurarnos de que todo el código de configuración dentro de esta constructor()función aún sea llamado.

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 única razón 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, inicializamos nuestro objeto de estado creando un objeto JavaScript, asignándole una propiedad o un par clave / valor, asignando el resultado de eso a this.state. Ahora, por supuesto, esto es solo un ejemplo aquí, por lo que realmente no he asignado un par clave / valor al objeto de estado, es solo un objeto vacío.

17

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

¿Por qué escribimos super (utilería)?

Y la esencia de esto es que es útil tener el hábito de pasarlo para evitar este escenario, que honestamente, no veo improbable 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 
  }
  // ...
}
15

Según el código fuente

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

debe pasar propscada vez que tenga accesorios y no los ponga this.propsmanualmente.

3
  • 1
    Todavía no tengo claro esto. si observa estos dos componentes , puede ver que uno llama super(props)y el otro no. Pero sus consumidores, ambos, establecen apoyos. ¿Cuál es la diferencia?
    Kyeotic
    23/10/15 a las 18:41
  • 1
    ¿Esto significa eso this.props = propsy super(props)son lo mismo? 15/12/15 a las 20:25
  • 1
    Esto no es verdad. ReactElement en realidad se establece this.propsdesde el "exterior", independientemente de lo que se haga en el constructor. 25 de enero de 2016 a las 14:58
11

super() se usa para llamar al constructor padre.

super(props)pasaría propsal constructor padre.

De su ejemplo, super(props)llamaría al React.Componentconstructor pasando propscomo argumento.

Más información en super: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/super

1
  • 23
    Sí, eso es lo que hace. ¿ Pero por qué ? ¿Y cuándo se requiere una de las dos formas en React?
    Bergi
    28 de septiembre de 2015 a las 12:27
5

Para react versión 16.6.3, usamos 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
};
4

Aquí no lo obtendremos en el constructor, por lo que devolverá undefined, pero podremos obtenerlo 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 usamos super (), también podemos buscar 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 usamos super (); podremos recuperar esto, pero this.props no estará definido en el constructor. Pero aparte del constructor, this.props no devolverá undefined.

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

La respuesta de Sophie Alpert

If you want to use this.props in the constructor, you need to pass props to super. Otherwise, it doesn’t matter because React sets .props on the instance from the outside immediately after calling the constructor.

4

Aquí está el violín que hice: jsfiddle.net . Muestra que los accesorios no se asignan en el constructor de forma predeterminada. Según tengo entendido, están involucrados 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. Quizás se cambie en las próximas versiones de React.