Qual é a diferença entre "super ()" e "super (adereços)" no React ao usar as classes es6?

532

Quando é que é importante passar propspara super(), e por quê?

class MyComponent extends React.Component {
  constructor(props) {
    super(); // or super(props) ?
  }
}
Misha Moroshko
fonte
7
Uma boa explicação também pode ser encontrada em overreacted.io/why-do-we-write-super-props
Amitesh

Respostas:

710

Há apenas um motivo para passar propspara super():

Quando você deseja acessar this.propsno construtor.

Passagem:

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

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

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

Note que passar ou não passar propsa supertem nenhum efeito sobre os usos posteriores do this.propslado de fora constructor. Ou seja render, os shouldComponentUpdatemanipuladores de eventos sempre têm acesso a ele.

Isso é explicitamente dito na resposta de Sophie Alpert a uma pergunta semelhante.


A documentação - Estado e Ciclo de Vida, Adicionando Estado Local a uma Classe, ponto 2 - recomenda:

Os componentes de classe sempre devem chamar o construtor base com props.

No entanto, nenhum motivo é fornecido. Podemos especular que seja por causa de subclassificação ou por compatibilidade futura.

(Obrigado @MattBrowne pelo link)

Robin Pokorny
fonte
16
Eu acho que você está correto, apesar das outras respostas terem mais votos. this.propsé, a undefinedmenos que seja passado para super(). De qualquer forma, não afeta a renderização ou a disponibilidade posterior this.propsda render()função.
Micros
3
@Rotareti, não, na verdade o resto da classe não depende dessa construção, esse é o ponto. O componente recebe props de uma maneira diferente da do parâmetro construtor. E desde que você passa os adereços iniciais super, você tem referência a eles no construtor.
Robin Pokorny
7
De acordo com a documentação Reagir, você deve sempre passar propspara super(): facebook.github.io/react/docs/... . Não sei por que, já que, como você menciona, this.propsé acessível de outros métodos de qualquer maneira ... talvez eles estejam recomendando isso para compatibilidade futura, caso versões futuras do React possam querer fazer algo com propso construtor?
Matt Browne
23
Talvez eu esteja apenas abrindo uma lata de worms aqui, mas por que passar propspara superquando, como você apontou, o propsparâmetro está disponível para uso no construtor e this.propsfunciona em qualquer outro lugar? Existe algum benefício em usar this.propsapenas props? É uma má prática desestruturar propso construtor? Acho que ainda estou deixando de ver um caso quando você já tinha precisa passar propspara super, mas eu estou disposto a apostar que é apenas a minha ignorância, ha.
Indiesquidge
9
Se você usar super(props), poderá chamar métodos que usam this.props do construtor , como this.doStuffUsingThisDotProps(), sem ter que passar o parâmetro props para esses métodos / funções. Acabei de escrever um construtor fazendo isso, o que aparentemente exigiria que eu o usasse super(props)primeiro, de acordo com as respostas a esta pergunta.
Victor Zamanian
54

Neste exemplo, você está estendendo a React.Componentclasse e, de acordo com a especificação do ES2015, um construtor de classe filho não pode usar thisaté super()que seja chamado; Além disso, os construtores de classe do ES2015 precisam chamar super()se forem subclasses.

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

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

Por contraste:

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

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

Mais detalhes de acordo com esta excelente resposta de estouro de pilha

Você pode ver exemplos de componentes criados estendendo a React.Componentclasse que não chama, super()mas notará que estes não possuem um constructor, portanto, por que não é necessário.

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

Um ponto de confusão que vi de alguns desenvolvedores com quem conversei é que os componentes que não possuem constructore, portanto, não chamam em super()lugar algum, ainda estão this.propsdisponíveis no render()método. Lembre-se de que esta regra e essa necessidade de criar uma thisligação para o constructorúnico se aplicam ao constructor.

Dave
fonte
15
Muito obrigado pela sua resposta, mas ela não responde à minha pergunta original (diferença entre super()e super(props)).
Misha Moroshko
46

Quando você passa propspara super, os objetos são atribuídos this. Dê uma olhada no seguinte cenário:

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

No entanto, quando você faz:

constructor(props) {
    super(props);
    console.log(this.props) //props will get logged.
}
Nahush Farkande
fonte
A melhor resposta da lista.
Basavaraj Hadimani
Esta resposta está parcialmente correta. Este exemplo é apenas para o método construtor. Por exemplo, mesmo se você não escrever super (props), this.props no método render ainda estará atribuído e disponível. A única razão mencionada acima é ao usar this.props no construtor.
Ofear
12

Conforme código fonte

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

você deve passar propstoda vez que tiver adereços e não os colocar this.propsmanualmente.

zerkms
fonte
1
Ainda não estou claro sobre isso. se você observar esses dois componentes , poderá ver uma chamada super(props)e a outra não. Mas seus consumidores definem adereços. Qual é a diferença?
Kyeotic
Isso significa isso this.props = propse super(props)é a mesma coisa?
reectrix
1
Isso não é verdade. ReactElement realmente define a this.propspartir de 'fora' - independentemente do que é feito no construtor.
precisa saber é o seguinte
11

Dan Abramov escreveu um artigo sobre este tópico:

Por que escrevemos super (adereços)?

E a essência disso é que é útil ter o hábito de contorná- lo para evitar esse cenário. Honestamente, não acho improvável que isso aconteça:

// 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
fonte
8

super() é usado para chamar o construtor pai.

super(props)passaria propspara o construtor pai.

Do seu exemplo, super(props)chamaria o React.Componentconstrutor de passagem propscomo argumento.

Mais informações em super: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/super

kspence
fonte
18
Sim, é o que faz. Mas porque ? E quando é uma das duas formas necessárias no React?
Bergi 28/09/2015
7

Ao implementar a constructor()função dentro de um componente React, super()é um requisito. Lembre-se de que seu MyComponentcomponente está estendendo ou emprestando funcionalidades da React.Componentclasse base.

Essa classe base tem uma constructor()função própria que possui algum código para configurar nosso componente React para nós.

Quando definimos uma constructor()função dentro de nossa MyComponentclasse, estamos essencialmente substituindo ou substituindo a constructor()função que está dentro da React.Componentclasse, mas ainda precisamos garantir que todo o código de instalação dentro dessa constructor()função ainda seja chamado.

Assim, para garantir que o React.Component's constructor()função é chamada, chamamos super(props). super(props)é uma referência à constructor()função dos pais , isso é tudo.

Temos que adicionar super(props)sempre que definirmos uma constructor()função dentro de um componente baseado em classe.

Caso contrário, veremos um erro dizendo que temos que ligar super(props).

A razão inteira para definir essa função constructor()é inicializar nosso objeto de estado.

Então, para inicializar nosso objeto de estado, sob a super chamada, vou escrever:

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

      this.state = {};
   }

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

Assim, definimos nosso constructor()método, inicializamos nosso objeto de estado criando um objeto JavaScript, atribuindo uma propriedade ou um par de chave / valor a ele, atribuindo o resultado disso a this.state. Agora é claro que este é apenas um exemplo aqui, então eu realmente não atribuí um par de chave / valor ao objeto de estado, é apenas um objeto vazio.

Daniel
fonte
4

Aqui está o violino que eu fiz: jsfiddle.net . Mostra que os adereços não estão atribuídos no construtor por padrão. Pelo que entendi, eles são avaliados no método React.createElement. Assim super(props)deve ser chamado somente quando assings construtor manualmente da superclasse propspara this.props. Se você apenas estender a React.Componentchamada super(props), nada fará com adereços. Talvez isso seja alterado nas próximas versões do React.

beshanoe
fonte
3

Aqui não conseguiremos isso no construtor, portanto ele retornará indefinido, mas poderemos buscá-lo fora da função do construtor

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

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

Se estivermos usando super (), também podemos buscar a variável "this" dentro do construtor

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

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

Então, quando estamos usando super (); seremos capazes de buscar isso, mas this.props será indefinido no construtor. Mas, além do construtor, this.props não retornará indefinido.

Se usarmos super (props), poderemos usar o valor this.props também dentro do construtor

Resposta de Sophie Alpert

Se você quiser usar this.props no construtor, precisará passar props para super. Caso contrário, isso não importa, porque o React define .props na instância de fora imediatamente após chamar o construtor.

VIKAS KOHLI
fonte
3

Para a versão 16.6.3 do react, usamos super (props) para inicializar o nome do elemento de estado : this.props.name

constructor(props){
    super(props);        
}
state = {
  name:this.props.name 
    //otherwise not defined
};
Shubham Kapoor
fonte