Qual è la differenza tra "super ()" e "super (oggetti di scena)" in React quando si usano le classi es6?


Risposte:


710

C'è solo una ragione per cui si deve passare propsa super():

Quando si desidera accedere this.propsal costruttore.

passando:

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

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

Non passando:

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', … }
    }
}

Nota che passare o non passare propsa nonsuper ha alcun effetto sugli usi successivi this.propsdell'esterno constructor. Che è render, shouldComponentUpdateo gestori di eventi sempre hanno accesso ad esso.

Questo è esplicitamente detto in una risposta di Sophie Alpert a una domanda simile.


La documentazione - Stato e ciclo di vita, Aggiunta di stato locale a una classe, punto 2 - raccomanda:

I componenti di classe devono sempre chiamare il costruttore di base con props.

Tuttavia, non viene fornito alcun motivo. Possiamo ipotizzare che sia per sottoclasse o per compatibilità futura.

(Grazie a @MattBrowne per il link)


16
Penso che tu abbia ragione, nonostante le altre risposte ottengano più voti. this.propsè a undefinedmeno che non venga passato a super(). In entrambi i casi, non influisce sul rendering successivo o sulla disponibilità di this.propsnella render()funzione.
Micros,

3
@Rotareti, no, in realtà il resto della classe non dipende da questo costrutto, questo è il punto. Il componente riceve gli oggetti di scena in modo diverso rispetto al parametro del costruttore. E dal momento che passi oggetti di scena iniziali super, hai riferimento a loro nel costruttore.
Robin Pokorny,

7
Secondo la documentazione di React, dovresti sempre passare propsa super(): facebook.github.io/react/docs/… . Non sono sicuro del perché, dal momento che come sottolineato this.propsè accessibile in altri modi in entrambi i modi ... forse lo stanno raccomandando per la compatibilità futura nel caso in cui le versioni future di React potrebbero voler fare qualcosa con propsil costruttore?
Matt Browne,

23
Forse sto solo aprendo una lattina di worm qui, ma perché mai passare propsa super, quando hai sottolineato, il propsparametro è proprio lì disponibile per noi da usare all'interno del costruttore e this.propsfunziona ovunque? C'è un vantaggio nell'usare this.propssolo oltre props? È una cattiva pratica da distruggere propsnel costruttore? Penso che sto ancora non riuscendo a vedere un caso in cui avessi mai bisogno di passare propsa super, ma io sono pronto a scommettere che è solo la mia ignoranza, ah.
indiesquidge,

9
Se lo usi super(props), puoi chiamare i metodi che usano this.props in dal costruttore , come this.doStuffUsingThisDotProps(), senza dover passare il parametro props a quei metodi / funzioni. Ho appena scritto un costruttore facendo questo, che apparentemente mi richiederebbe di usare super(props)prima, secondo le risposte a questa domanda.
Victor Zamanian,

54

In questo esempio, si sta estendendo la React.Componentclasse e, in base alle specifiche ES2015, un costruttore di classi figlio non può utilizzare thisfino a quando non super()viene chiamato; inoltre, i costruttori di classe ES2015 devono chiamare super()se sono sottoclassi.

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

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

Al contrario:

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

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

Maggiori dettagli su questa eccellente risposta di overflow dello stack

Potresti vedere esempi di componenti creati estendendo la React.Componentclasse che non chiama super()ma noterai che questi non hanno un constructor, quindi perché non è necessario.

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

Un punto di confusione che ho visto da alcuni sviluppatori con cui ho parlato è che i componenti che non hanno constructore quindi non chiamano da super()nessuna parte, sono ancora this.propsdisponibili nel render()metodo. Ricorda che questa regola e questa necessità di creare un'associazione thisper l' constructorunica si applica al constructor.


15
Grazie mille per la tua risposta, ma non risponde alla mia domanda originale (differenza tra super()e super(props)).
Misha Moroshko,

46

Quando passi propsa super, gli oggetti di scena vengono assegnati a this. Dai un'occhiata al seguente scenario:

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

Come mai quando lo fai:

constructor(props) {
    super(props);
    console.log(this.props) //props will get logged.
}

La migliore risposta nell'elenco.
Basavaraj Hadimani,

Questa risposta è per metà corretta, questo esempio è solo per il metodo del costruttore. Ad esempio, anche se non scrivi super (oggetti di scena), this.props con il metodo di rendering sarà comunque assegnato e disponibile. L'unico motivo menzionato sopra è quando si utilizza this.props nel costruttore.
Ofear,

12

Secondo il codice sorgente

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

devi passare propsogni volta che hai oggetti di scena e non li metti this.propsmanualmente.


1
Non sono ancora chiaro su questo. se guardi questi due componenti , puoi vedere una chiamata super(props)e l'altra no. Ma i loro consumatori hanno entrambi puntellato. Qual è la differenza?
Kyeotic,

Significa questo this.props = propse super(props)sono la stessa cosa?
reectrix,

1
Questo non è vero. ReactElement in realtà imposta this.propsdall'esterno, indipendentemente da ciò che viene fatto nel costruttore.
Robin Pokorny,

11

Dan Abramov ha scritto un articolo su questo argomento:

Perché scriviamo super (oggetti di scena)?

E l'essenza di ciò è che è utile avere l'abitudine di passarlo per evitare questo scenario, che onestamente, non vedo improbabile che accada:

// 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 
  }
  // ...
}


7

Quando si implementa la constructor()funzione all'interno di un componente React, super()è un requisito. Tieni presente che il MyComponentcomponente estende o prende in prestito funzionalità dalla React.Componentclasse base.

Questa classe base ha una sua constructor()funzione che contiene del codice al suo interno, per impostare il nostro componente React per noi.

Quando definiamo una constructor()funzione all'interno della nostra MyComponentclasse, essenzialmente, sovrascriviamo o sostituiamo la constructor()funzione che si trova all'interno della React.Componentclasse, ma dobbiamo ancora assicurarci che tutto il codice di installazione all'interno di questa constructor()funzione venga ancora chiamato.

Quindi, per garantire che la React.Component's constructor()funzione viene chiamata, noi chiamiamo super(props). super(props)è un riferimento alla constructor()funzione dei genitori , questo è tutto.

Dobbiamo aggiungere super(props)ogni volta che definiamo una constructor()funzione all'interno di un componente di classe.

Altrimenti vedremo un errore che dice che dobbiamo chiamare super(props).

L'intero motivo per definire questa constructor()funzione è inizializzare il nostro oggetto stato.

Quindi, al fine di inizializzare il nostro oggetto di stato, sotto la super chiamata scriverò:

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

      this.state = {};
   }

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

Quindi abbiamo definito il nostro constructor()metodo, inizializzato il nostro oggetto stato creando un oggetto JavaScript, assegnandogli una proprietà o una coppia chiave / valore, assegnandone il risultato this.state. Ora ovviamente questo è solo un esempio qui, quindi non ho assegnato una coppia chiave / valore all'oggetto stato, è solo un oggetto vuoto.


4

Ecco il violino che ho realizzato: jsfiddle.net . Mostra che gli oggetti di scena sono assegnati non nel costruttore per impostazione predefinita. A quanto ho capito, sono valutati nel metodo React.createElement. Quindi super(props)dovrebbe essere chiamato solo quando assegna l'costruttore manualmente della superclasse propsa this.props. Se estendi semplicemente la React.Componentchiamata super(props)non farà nulla con i puntelli. Forse sarà cambiato nelle prossime versioni di React.


3

Qui non lo avremo nel costruttore, quindi tornerà indefinito, ma saremo in grado di recuperarlo al di fuori della funzione del costruttore

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

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

Se stiamo usando super (), allora possiamo recuperare anche la variabile "this" all'interno del costruttore

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

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

Quindi quando stiamo usando super (); saremo in grado di recuperarlo, ma this.props non sarà definito nel costruttore. Ma a parte il costruttore, this.props non tornerà indefinito.

Se usiamo super (oggetti di scena), allora possiamo usare questo valore anche all'interno del costruttore

La risposta di Sophie Alpert

Se vuoi usare this.props nel costruttore, devi passare oggetti di scena a super. Altrimenti, non importa perché React imposta .props sull'istanza dall'esterno immediatamente dopo aver chiamato il costruttore.


3

Per la versione di reazione 16.6.3, utilizziamo super (props) per inizializzare il nome dell'elemento state : this.props.name

constructor(props){
    super(props);        
}
state = {
  name:this.props.name 
    //otherwise not defined
};
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.