Quand est-il important de passer props
à super()
et pourquoi?
class MyComponent extends React.Component {
constructor(props) {
super(); // or super(props) ?
}
}
Il y a une seule raison pour laquelle il faut passer props
à super()
:
Lorsque vous souhaitez accéder à this.props
dans le constructeur.
Qui passe:
class MyComponent extends React.Component {
constructor(props) {
super(props)
console.log(this.props)
// -> { icon: 'home', … }
}
}
Ne passant pas:
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', … }
}
}
Notez que le fait de passer ou non de props
à super
n'a que aucun effet sur les utilisations ultérieures de this.props
extérieur de constructor
. C'est render
, shouldComponentUpdate
ou les gestionnaires d'événements always y ont accès.
Ceci est explicitement dit dans un réponse de Sophie Alpert à une question similaire.
La documentation — État et cycle de vie, Ajout de l'état local à une classe, point 2 — recommande:
Les composants de classe doivent toujours appeler le constructeur de base avec
props
.
Cependant, aucune raison n'est fournie. Nous pouvons supposer que cela est dû soit à un sous-classement, soit à une compatibilité future.
(Merci @MattBrowne pour le lien)
Dans cet exemple, vous étendez la classe React.Component
et, conformément à la spécification ES2015, un constructeur de classe enfant ne peut pas utiliser this
tant que l'appel de super()
n'a pas eu lieu; De plus, les constructeurs de classe ES2015 doivent appeler super()
s'ils sont des sous-classes.
class MyComponent extends React.Component {
constructor() {
console.log(this); // Reference Error
}
render() {
return <div>Hello {this.props.name}</div>;
}
}
Par contre:
class MyComponent extends React.Component {
constructor() {
super();
console.log(this); // this logged to console
}
render() {
return <div>Hello {this.props.name}</div>;
}
}
Plus de détails selon cette excellente réponse de débordement de pile
Vous pouvez voir des exemples de composants créés en étendant la classe React.Component
qui n’appellent pas super()
mais vous remarquerez qu’ils n’ont pas de constructor
, ce qui explique pourquoi ce n’est pas nécessaire.
class MyOtherComponent extends React.Component {
render() {
return <div>Hi {this.props.name}</div>;
}
}
Un point de confusion que j'ai vu chez certains développeurs avec lesquels j'ai parlé est que les composants qui n'ont pas de constructor
et donc n'appellent pas super()
nulle part, ont toujours this.props
disponible dans la méthode render()
. Rappelez-vous que cette règle et cette nécessité de créer une liaison this
pour la constructor
s'applique uniquement à la constructor
.
Lorsque vous passez de props
à super
, les accessoires sont affectés à this
. Examinez le scénario suivant:
constructor(props) {
super();
console.log(this.props) //undefined
}
Comment quand tu fais:
constructor(props) {
super(props);
console.log(this.props) //props will get logged.
}
Selon code source
function ReactComponent(props, context) {
this.props = props;
this.context = context;
}
vous devez passer props
chaque fois que vous avez des accessoires et vous ne les mettez pas dans this.props
manuellement.
super()
est utilisé pour appeler le constructeur parent.
super(props)
transmettrait props
au constructeur parent.
A partir de votre exemple, super(props)
appellerait le constructeur React.Component
en passant props
en argument.
Plus d'informations sur super
: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/super
Voici le violon que j'ai fait: https://jsfiddle.net/beshanoe/zpxbLw4j/1/ . Cela montre que les accessoires ne sont pas affectés par défaut au constructeur. Si je comprends bien, ils sont évalués dans la méthode React.createElement
. Par conséquent, super(props)
ne devrait être appelé que lorsque le constructeur de la superclasse associe manuellement props
à this.props
. Si vous prolongez le React.Component
, appeler super(props)
ne fera rien avec les accessoires. Peut-être que cela sera changé dans les prochaines versions de React.
Dan Abramov a écrit un article sur ce sujet:
https://overreacted.io/why-do-we-write-super-props/
Et l’essentiel est qu’il est utile d’avoir l’habitude de le passer pour éviter ce scénario, honnêtement, je ne vois pas cela qui risque de se produire:
// 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
}
// ...
}
Lors de l'implémentation de la fonction constructor()
dans un composant React, super()
est obligatoire. N'oubliez pas que votre composant MyComponent
est en train d'étendre ou d'emprunter des fonctionnalités de la classe de base React.Component
.
Cette classe de base possède sa propre fonction constructor()
, qui contient du code, pour configurer notre composant React pour nous.
Lorsque nous définissons une fonction constructor()
dans notre classe MyComponent
, nous substituons ou remplaçons la fonction constructor()
qui se trouve dans la classe React.Component
, mais nous devons néanmoins nous assurer que tout le code de configuration à l'intérieur de cette fonction constructor()
est toujours appelé.
Pour que la fonction constructor()
de React.Component
’s soit appelée, nous appelons super(props)
. super(props)
est une référence à la fonction constructor()
des parents, c’est tout.
Nous devons ajouter super(props)
chaque fois que nous définissons une fonction constructor()
dans un composant basé sur une classe.
Si nous ne le faisons pas, nous verrons une erreur disant que nous devons appeler super(props)
.
La raison entière pour définir cette fonction constructor()
est d’initialiser notre objet d’état.
Donc, pour initialiser notre objet d'état, sous le super appel, je vais écrire:
class App extends React.Component {
constructor(props) {
super(props);
this.state = {};
}
// React says we have to define render()
render() {
return <div>Hello world</div>;
}
};
Nous avons donc défini notre méthode constructor()
, initialisé notre objet state en créant un objet JavaScript, en lui affectant une propriété ou une paire clé/valeur, en attribuant le résultat à this.state
. Bien sûr, ceci n’est qu’un exemple ici. Je n’ai donc pas vraiment affecté de paire clé/valeur à l’objet state, c’est un objet vide.
Ici, nous n'obtiendrons pas ceci dans le constructeur, il retournera donc undefined, mais nous pourrons extraire cela en dehors de la fonction constructeur
class MyComponent extends React.Component {
constructor() {
console.log(this); // Reference Error i.e return undefined
}
render() {
return <div>Hello {this.props.name}</div>;
}
}
Si nous utilisons super (), nous pouvons aussi récupérer la variable "this" dans le constructeur
class MyComponent extends React.Component {
constructor() {
super();
console.log(this); // this logged to console
}
render() {
return <div>Hello {this.props.name}</div>;
}
}
Donc quand on utilise super (); nous pourrons aller chercher ça mais this.props sera indéfini dans le constructeur. Mais à part constructeur, this.props ne retournera pas indéfini.
Si nous utilisons super (props), nous pouvons aussi utiliser la valeur this.props dans le constructeur
Si vous voulez utiliser this.props dans le constructeur, vous devez passer les accessoires à super. Sinon, cela n’a aucune importance, car React définit .props sur l'instance de l'extérieur immédiatement après avoir appelé le constructeur.
Pour réagir à la version 16.6.3, nous utilisons super (props) pour initialiser l’élément d’étatname: this.props.name
constructor(props){
super(props);
}
state = {
name:this.props.name
//otherwise not defined
};