Apa perbedaan antara "super ()" dan "super (alat peraga)" di React saat menggunakan kelas es6?

532

Ketika itu penting untuk lulus propske super(), dan mengapa?

class MyComponent extends React.Component {
  constructor(props) {
    super(); // or super(props) ?
  }
}
Misha Moroshko
sumber
7
Penjelasan yang baik juga dapat ditemukan di overreacted.io/why-do-we-write-super-props
Amitesh

Jawaban:

710

Hanya ada satu alasan ketika salah satu kebutuhan untuk lulus propske super():

Ketika Anda ingin mengakses this.propsdi konstruktor.

Lewat:

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

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

Tidak lewat:

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

Perhatikan bahwa yang lewat atau tidak lulus propsuntuk supermemiliki tidak berpengaruh pada penggunaan selanjutnya dari this.propsluar constructor. Artinya render, shouldComponentUpdate, atau event handler selalu memiliki akses ke sana.

Ini secara eksplisit dikatakan dalam satu jawaban Sophie Alpert untuk pertanyaan serupa.


Dokumentasinya — Status dan Siklus Hidup, Menambahkan Status Lokal ke Kelas, poin 2 — merekomendasikan:

Komponen kelas harus selalu memanggil konstruktor dasar dengan props.

Namun, tidak ada alasan yang diberikan. Kami dapat berspekulasi itu karena subkelas atau untuk kompatibilitas di masa mendatang.

(Terima kasih @MattBrowne untuk tautannya)

Robin Pokorny
sumber
16
Saya pikir Anda benar, meskipun jawaban lain mendapatkan lebih banyak suara. this.propsadalah undefinedkecuali diteruskan ke super(). Either way, itu tidak mempengaruhi kemudian render atau ketersediaan this.propsdi render()fungsi.
Mikrofon
3
@Rotareti, tidak, sebenarnya seluruh kelas tidak bergantung pada konstruk ini, itu intinya. Komponen menerima alat peraga dengan cara yang berbeda dengan parameter konstruktor. Dan karena Anda memberikan alat peraga awal super, Anda memiliki referensi ke mereka di konstruktor.
Robin Pokorny
7
Menurut dokumentasi Bereaksi, Anda harus selalu beralih propske super(): facebook.github.io/react/docs/… . Saya tidak yakin mengapa, karena seperti yang Anda tunjukkan this.propsdapat diakses dengan metode lain ... mungkin mereka merekomendasikan ini untuk kompatibilitas di masa depan jika versi React masa depan mungkin ingin melakukan sesuatu dengan propskonstruktor?
Matt Browne
23
Mungkin aku hanya membuka sekaleng cacing di sini, tapi mengapa pernah lulus propsuntuk supersaat, seperti yang Anda menunjukkan, propsparameter benar ada tersedia bagi kita untuk menggunakan dalam constructor , dan this.propsbekerja di tempat lain? Apakah ada manfaatnya menggunakan this.propslebih dari sekadar props? Apakah praktik yang buruk merusak propsdi dalam konstruktor? Saya pikir saya masih gagal untuk melihat kasus ketika Anda pernah harus lulus propsuntuk super, tapi aku berani bertaruh itu hanya ketidaktahuan saya, ha.
indiesquidge
9
Jika Anda menggunakan super(props), Anda dapat memanggil metode yang digunakan this.props di dari konstruktor , seperti this.doStuffUsingThisDotProps(), tanpa harus meneruskan parameter alat peraga ke metode / fungsi tersebut. Saya baru saja menulis konstruktor melakukan ini, yang tampaknya akan mengharuskan saya untuk menggunakan super(props)pertama, sesuai dengan jawaban untuk pertanyaan ini.
Victor Zamanian
54

Dalam contoh ini, Anda memperluas React.Componentkelas, dan sesuai spesifikasi ES2015, konstruktor kelas anak tidak dapat menggunakan thissampai super()dipanggil; juga, konstruktor kelas ES2015 harus memanggil super()jika mereka adalah subkelas.

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

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

Sebaliknya:

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

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

Lebih detail sesuai jawaban stack overflow yang luar biasa ini

Anda dapat melihat contoh komponen yang dibuat dengan memperluas React.Componentkelas yang tidak memanggil super()tetapi Anda akan melihat ini tidak memiliki constructor, karenanya mengapa tidak perlu.

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

Satu titik kebingungan yang saya lihat dari beberapa pengembang yang saya ajak bicara adalah bahwa komponen yang tidak memiliki constructordan karena itu tidak menelepon ke super()mana pun, masih this.propsada dalam render()metode ini. Ingatlah bahwa aturan ini dan kebutuhan ini untuk membuat thisikatan constructorhanya berlaku untuk constructor.

Dave
sumber
15
Terima kasih banyak atas jawaban Anda, tetapi tidak menjawab pertanyaan awal saya (perbedaan antara super()dan super(props)).
Misha Moroshko
46

Ketika Anda beralih propske super, alat peraga ditugaskan this. Lihatlah skenario berikut:

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

Bagaimana pun saat Anda melakukannya:

constructor(props) {
    super(props);
    console.log(this.props) //props will get logged.
}
Nahush Farkande
sumber
Jawaban terbaik dalam daftar.
Basavaraj Hadimani
Jawaban ini setengah benar, Contoh ini hanya untuk metode konstruktor. Misalnya, bahkan jika Anda tidak menulis super (props), this.props di bawah metode render akan tetap ditugaskan dan tersedia. Satu-satunya alasan yang disebutkan di atas adalah ketika menggunakan this.props di konstruktor.
Ofear
12

Sesuai kode sumber

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

Anda harus lulus propssetiap kali Anda memiliki alat peraga dan Anda tidak memasukkannya this.propssecara manual.

zerkms
sumber
1
Saya masih tidak jelas tentang ini. jika Anda melihat ini dua komponen , Anda dapat melihat satu panggilan super(props)dan yang lainnya tidak. Namun konsumen mereka sama-sama memasang alat peraga. Apa bedanya?
Kyeotic
Apakah ini berarti bahwa this.props = propsdan super(props)adalah hal yang sama?
reectrix
1
Ini tidak benar. ReactElement sebenarnya this.propsberasal dari 'luar' - terlepas dari apa yang dilakukan dalam konstruktor.
Robin Pokorny
11

Dan Abramov menulis artikel tentang topik ini:

Kenapa Kita Menulis super (alat peraga)?

Dan intinya adalah bahwa memiliki kebiasaan melewatinya untuk menghindari skenario ini sangat membantu, jujur, saya tidak melihat hal itu tidak mungkin terjadi:

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

super() digunakan untuk memanggil konstruktor induk.

super(props)akan diteruskan propske konstruktor induk.

Dari contoh Anda, super(props)akan memanggil React.Componentkonstruktor yang lewat propssebagai argumen.

Informasi lebih lanjut tentang super: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/super

kspence
sumber
18
Ya, itulah fungsinya. Tapi mengapa ? Dan kapan salah satu dari dua bentuk ini diperlukan dalam Bereaksi?
Bergi
7

Ketika menerapkan constructor()fungsi di dalam komponen Bereaksi, super()adalah persyaratan. Ingatlah bahwa MyComponentkomponen Anda memperluas atau meminjam fungsionalitas dari React.Componentkelas dasar.

Kelas dasar ini memiliki constructor()fungsi sendiri yang memiliki beberapa kode di dalamnya, untuk mengatur komponen Bereaksi kami untuk kami.

Ketika kita mendefinisikan suatu constructor()fungsi di dalam MyComponentkelas kita, kita pada dasarnya, menimpa atau mengganti constructor()fungsi yang ada di dalam React.Componentkelas, tetapi kita masih perlu memastikan bahwa semua kode pengaturan di dalam constructor()fungsi ini masih dipanggil.

Jadi untuk memastikan bahwa React.Component's constructor()fungsi dipanggil, kita sebut super(props). super(props)adalah referensi ke constructor()fungsi orang tua , itu saja.

Kita harus menambahkan super(props)setiap kali kita mendefinisikan suatu constructor()fungsi di dalam komponen berbasis kelas.

Jika tidak, kita akan melihat kesalahan yang mengatakan bahwa kita harus menelepon super(props).

Seluruh alasan untuk mendefinisikan constructor()fungsi ini adalah untuk menginisialisasi objek negara kita.

Jadi untuk menginisialisasi objek keadaan kita, di bawah panggilan super saya akan menulis:

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

      this.state = {};
   }

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

Jadi kami telah mendefinisikan constructor()metode kami , menginisialisasi objek negara kami dengan membuat objek JavaScript, menetapkan properti atau pasangan kunci / nilai, menetapkan hasil untuk itu this.state. Sekarang tentu saja ini hanya contoh di sini jadi saya belum benar-benar menetapkan pasangan kunci / nilai ke objek keadaan, itu hanya objek kosong.

Daniel
sumber
4

Ini biola yang saya buat: jsfiddle.net . Ini menunjukkan bahwa alat peraga ditetapkan tidak secara default di konstruktor. Seperti yang saya mengerti mereka menggunakan metode ini React.createElement. Oleh karena itu super(props)harus disebut hanya ketika assings konstruktor manual superclass ini propsuntuk this.props. Jika Anda hanya memperpanjang React.Componentpanggilan super(props)tidak akan melakukan apa pun dengan alat peraga. Mungkin ini akan diubah di React versi berikutnya.

beshanoe
sumber
3

Di sini kita tidak akan mendapatkan ini di konstruktor sehingga akan kembali tidak terdefinisi, tetapi kita akan dapat mengambil ini di luar fungsi konstruktor

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

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

Jika kita menggunakan super (), maka kita dapat mengambil variabel "ini" di dalam konstruktor juga

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

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

Jadi saat kita menggunakan super (); kita akan dapat mengambil ini tetapi this.props tidak akan ditentukan dalam konstruktor. Tapi selain konstruktor, this.props tidak akan kembali tanpa terdefinisi.

Jika kita menggunakan super (alat peraga), maka kita dapat menggunakan nilai this.props di dalam konstruktor juga

Jawaban Sophie Alpert

Jika Anda ingin menggunakan this.props di konstruktor, Anda harus meneruskan alat peraga ke super. Kalau tidak, itu tidak masalah karena Bereaksi menetapkan .prop pada instance dari luar segera setelah memanggil konstruktor.

VIKAS KOHLI
sumber
3

Untuk bereaksi versi 16.6.3, kami menggunakan super (alat peraga) untuk menginisialisasi nama elemen negara : this.props.name

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