Quelle est la différence entre «super ()» et «super (accessoires)» dans React lors de l'utilisation des classes es6?

532

Quand est - il important de passer propsà super(), et pourquoi?

class MyComponent extends React.Component {
  constructor(props) {
    super(); // or super(props) ?
  }
}
Misha Moroshko
la source
7
Une bonne explication peut également être trouvée à overreacted.io/why-do-we-write-super-props
Amitesh

Réponses:

710

Il n'y a qu'une seule raison quand il faut passer propsà super():

Lorsque vous souhaitez accéder this.propsau constructeur.

Qui passe:

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

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

Ne passe 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 passer ou ne pas passer propsà supern'a aucun effet sur les utilisations ultérieures de l' this.propsextérieur constructor. Autrement dit render, shouldComponentUpdateou les gestionnaires d'événements y ont toujours accès.

Cela est dit explicitement dans une réponse de Sophie Alpert à une question similaire.


La documentation - État et cycle de vie, Ajout d'un é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 spéculer que c'est à cause du sous-classement ou pour une future compatibilité.

(Merci @MattBrowne pour le lien)

Robin Pokorny
la source
16
Je pense que vous avez raison, malgré les autres réponses qui obtiennent plus de votes. this.propsest undefinedsauf si transmis à super(). Dans tous les cas, cela n'affecte pas le rendu ou la disponibilité ultérieurs de this.propsla render()fonction.
Micros
3
@Rotareti, non, en fait le reste de la classe ne dépend pas de cette construction, c'est le point. Le composant reçoit les accessoires d'une manière différente de celle du paramètre constructeur. Et puisque vous passez des accessoires initiaux à super, vous y faites référence dans le constructeur.
Robin Pokorny
7
Selon la documentation de React, vous devez toujours passer propsà super(): facebook.github.io/react/docs/… . Je ne sais pas pourquoi, car comme vous le signalez this.propsest accessible de toute façon ... peut-être qu'ils recommandent cela pour une compatibilité future au cas où les futures versions de React voudraient faire quelque chose avec propsdans le constructeur?
Matt Browne
23
Peut - être que je suis juste d' ouvrir une boîte de Pandore, mais pourquoi jamais passer propsà superquand, comme vous l' avez dit, le propsparamètre est disponible là pour nous d'utiliser dans le constructeur , et this.propsfonctionne partout ailleurs? Y a-t-il un avantage à utiliser this.propsplus que juste props? Est-ce une mauvaise pratique de détruire propsle constructeur? Je pense que je suis encore à défaut de voir un cas où vous auriez jamais besoin de passer propsà super, mais je suis prêt à parier que c'est juste mon ignorance, ha.
indiesquidge
9
Si vous utilisez super(props), vous pouvez appeler des méthodes qui utilisent this.props in depuis un constructeur , comme this.doStuffUsingThisDotProps(), sans avoir à transmettre le paramètre props à ces méthodes / fonctions. Je viens d'écrire un constructeur faisant cela, ce qui me demanderait apparemment d'utiliser d' super(props)abord, selon les réponses à cette question.
Victor Zamanian
54

Dans cet exemple, vous étendez la React.Componentclasse et, selon la spécification ES2015, un constructeur de classe enfant ne peut pas utiliser thisavant d' super()avoir été appelé; aussi, 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 React.Componentclasse qui n'appelle pas, super()mais vous remarquerez qu'ils n'en ont pas constructor, d'où 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 de la part de certains développeurs à qui j'ai parlé est que les composants qui n'ont pas constructoret donc n'appellent super()nulle part, sont toujours this.propsdisponibles dans la render()méthode. N'oubliez pas que cette règle et cette nécessité de créer une thisliaison pour le constructorseul s'applique au constructor.

Dave
la source
15
Merci beaucoup pour votre réponse, mais cela ne répond pas à ma question d'origine (différence entre super()et super(props)).
Misha Moroshko
46

Lorsque vous passez propsà super, les accessoires sont affectés à this. Jetez un œil au scénario suivant:

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

Comment quand vous le faites:

constructor(props) {
    super(props);
    console.log(this.props) //props will get logged.
}
Nahush Farkande
la source
La meilleure réponse de la liste.
Basavaraj Hadimani
Cette réponse est à moitié correcte, cet exemple concerne uniquement la méthode constructeur. Par exemple, même si vous n'écrivez pas super (props), this.props sous la méthode de rendu sera toujours assigné et disponible. La seule raison mentionnée ci-dessus est lors de l'utilisation de this.props dans le constructeur.
Ofear
12

Selon le code source

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

vous devez passer propschaque fois que vous avez des accessoires et vous ne les mettez pas this.propsmanuellement.

zerkms
la source
1
Je ne suis toujours pas clair à ce sujet. si vous regardez ces deux composants , vous pouvez voir l'un des appels super(props)et l'autre non. Mais leurs consommateurs ont tous deux mis des accessoires. Quelle est la différence?
Kyeotic
Est-ce à dire cela this.props = propset super(props)sont la même chose?
reectrix
1
Ce n'est pas vrai. ReactElement définit en fait this.propsde «l'extérieur» - indépendamment de ce qui est fait dans le constructeur.
Robin Pokorny
11

Dan Abramov a écrit un article sur ce sujet:

Pourquoi écrivons-nous des super (accessoires)?

Et l'essentiel est qu'il est utile d'avoir l'habitude de le passer pour éviter ce scénario, honnêtement, je ne pense pas que cela se produira:

// 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
la source
8

super() est utilisé pour appeler le constructeur parent.

super(props) passerait props au constructeur parent.

De votre exemple, super(props)appellerait le React.Componentconstructeur passantprops comme argument.

Plus d'informations sur super: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/super

kspence
la source
18
Oui, c'est ce que ça fait. Mais pourquoi ? Et quand l' une des deux formes est-elle requise dans React?
Bergi
7

Lors de l'implémentation de la constructor()fonction à l'intérieur d'un composant React, super()est une exigence. N'oubliez pas que votre MyComponentcomposant étend ou emprunte des fonctionnalités à la React.Componentclasse de base.

Cette classe de base a constructor()sa propre fonction qui contient du code pour configurer notre composant React pour nous.

Lorsque nous définissons une constructor()fonction à l'intérieur de notre MyComponentclasse, nous remplaçons ou remplaçons essentiellement la constructor()fonction qui est à l'intérieur de la React.Componentclasse, mais nous devons toujours nous assurer que tout le code de configuration à l'intérieur de cette classeconstructor() fonction est toujours appelé.

Donc , pour faire en sorte que la React.Componentde » constructor()la fonction est appelée, nous appelons super(props). super(props)est une référence à la constructor()fonction des parents , c'est tout.

Nous devons ajouter super(props)chaque fois que nous définissons une constructor()fonction à l'intérieur d'un composant basé sur une classe.

Si nous ne le faisons pas, nous verrons une erreur indiquant que nous devons appeler super(props).

La raison de la définition de cette constructor()fonction est d'initialiser notre objet d'état.

Donc, afin d'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 constructor()méthode, initialisé notre objet d'état en créant un objet JavaScript, en lui attribuant une propriété ou une paire clé / valeur, en attribuant le résultat à this.state. Maintenant, bien sûr, ce n'est qu'un exemple ici, donc je n'ai pas vraiment attribué de paire clé / valeur à l'objet d'état, c'est juste un objet vide.

Daniel
la source
4

Voici le violon que j'ai fait: jsfiddle.net . Il montre que les accessoires ne sont pas attribués par défaut dans le constructeur. Si je comprends bien, ils sont évalués dans la méthode React.createElement. Par conséquent, il super(props)ne devrait être appelé que lorsque le constructeur de la superclasse se connecte manuellement propsà this.props. Si vous prolongez simplement l' React.Componentappel, super(props)cela ne fera rien avec les accessoires. Peut-être que cela sera changé dans les prochaines versions de React.

beshanoe
la source
3

Ici, nous n'obtiendrons pas cela dans le constructeur, il retournera donc indéfini, mais nous pourrons le récupérer 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" à l'intérieur du constructeur

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

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

Donc, lorsque nous utilisons super (); nous pourrons récupérer ceci mais this.props ne sera pas défini dans le constructeur. Mais à part constructeur, this.props ne retournera pas indéfini.

Si nous utilisons super (props), nous pouvons également utiliser la valeur this.props à l'intérieur du constructeur

Réponse de Sophie Alpert

Si vous souhaitez utiliser this.props dans le constructeur, vous devez passer props à super. Sinon, cela n'a pas d'importance parce que React définit .props sur l'instance de l'extérieur immédiatement après avoir appelé le constructeur.

VIKAS KOHLI
la source
3

Pour react version 16.6.3, nous utilisons super (props) pour initialiser le nom de l' élément state : this.props.name

constructor(props){
    super(props);        
}
state = {
  name:this.props.name 
    //otherwise not defined
};
shubham kapoor
la source