¿Cuál es la diferencia entre "super()" y "super(props)" en React cuando se usan clases es6?
¿Cuándo es importante pasar props
a super()
y por qué?
class MyComponent extends React.Component {
constructor(props) {
super(); // or super(props) ?
}
}
Sólo hay una razón por la que es necesario pasar props
a super()
:
Cuando quieras acceder this.props
en constructor.
Paso:
class MyComponent extends React.Component {
constructor(props) {
super(props)
console.log(this.props)
// -> { icon: 'home', … }
}
}
No pasar:
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 props
a no super
tiene ningún efecto en usos posteriores de this.props
outside constructor
. Es decir render
, shouldComponentUpdate
o 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 la clase siempre deben llamar al constructor base con
props
.
Sin embargo, no se proporciona ningún motivo. Podemos especular que se debe a la subclasificación o a la compatibilidad futura.
(Gracias @MattBrowne por el enlace)
En este ejemplo, está ampliando la React.Component
clase y, según la especificación ES2015, un constructor de clase secundaria no puede utilizarlo this
hasta que super()
haya sido llamado; Además, los constructores de clases de ES2015 deben 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
Es posible que vea ejemplos de componentes creados al extender la React.Component
clase que no llaman, super()
pero notará que 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 en algunos desarrolladores con los que he hablado es que los componentes que no tienen constructor
y, por lo tanto, no llaman super()
a ningún lado, todavía están this.props
disponibles en el render()
método. Recuerde que esta regla y esta necesidad de crear un this
enlace para el constructor
solo se aplica al constructor
.
Cuando pasas props
a 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 haces:
constructor(props) {
super(props);
console.log(this.props) //props will get logged.
}
Al implementar la constructor()
función dentro de un componente de React, super()
es un requisito. Tenga en cuenta que su MyComponent
componente está ampliando o tomando prestada funcionalidad de la React.Component
clase base.
Esta clase base tiene una constructor()
función propia que tiene algo de código dentro para configurar nuestro componente React por nosotros.
Cuando definimos una constructor()
función dentro de nuestra MyComponent
clase, esencialmente estamos anulando o reemplazando la constructor()
función que está dentro de la React.Component
clase, pero aún debemos asegurarnos de que constructor()
se siga llamando a todo el código de configuración dentro de esta función.
Entonces, para asegurarnos de que se llame a la React.Component
función constructor()
, llamamos a 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 indica 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 superllamada 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>;
}
};
Entonces, definimos 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 a this.state
. Ahora, por supuesto, esto es solo un ejemplo, por lo que en realidad no he asignado un par clave/valor al objeto de estado, es solo un objeto vacío.
Dan Abramov escribió un artículo sobre este tema:
¿Por qué escribimos super(props)?
Y lo esencial 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
}
// ...
}