Bagaimana Anda memutuskan, bagaimana Anda memilih di antara ketiganya berdasarkan tujuan / ukuran / properti / perilaku komponen kami?
Memperluas dari React.PureComponent
atau dari React.Component
dengan shouldComponentUpdate
metode kustom memiliki implikasi kinerja. Menggunakan komponen fungsional stateless adalah pilihan "arsitektural" dan tidak memiliki manfaat kinerja di luar kotak (belum).
Untuk komponen sederhana, hanya untuk presentasi yang perlu mudah digunakan kembali, lebih memilih komponen fungsional stateless. Dengan cara ini Anda yakin mereka dipisahkan dari logika aplikasi yang sebenarnya, bahwa mereka sangat mudah untuk diuji dan bahwa mereka tidak memiliki efek samping yang tidak terduga. Pengecualiannya adalah jika karena alasan tertentu Anda memiliki banyak dari mereka atau jika Anda benar-benar perlu mengoptimalkan metode render mereka (karena Anda tidak dapat menentukan shouldComponentUpdate
komponen fungsional stateless).
Perluas PureComponent
jika Anda tahu output Anda bergantung pada properti / keadaan sederhana ("sederhana" yang berarti tidak ada struktur data bersarang, karena PureComponent melakukan perbandingan yang dangkal) DAN Anda perlu / bisa mendapatkan beberapa peningkatan kinerja.
Perpanjang Component
dan terapkan sendiri shouldComponentUpdate
jika Anda memerlukan peningkatan kinerja dengan melakukan logika perbandingan khusus antara properti dan properti berikutnya / saat ini. Misalnya, Anda dapat dengan cepat melakukan perbandingan mendalam menggunakan lodash # isEqual:
class MyComponent extends Component {
shouldComponentUpdate (nextProps, nextState) {
return !_.isEqual(this.props, nextProps) || !_.isEqual(this.state, nextState);
}
}
Juga, menerapkan milik Anda sendiri shouldComponentUpdate
atau memperluas dari PureComponent
adalah optimasi, dan seperti biasa Anda harus mulai melihat ke dalamnya hanya jika Anda memiliki masalah kinerja ( hindari optimasi prematur ). Sebagai aturan praktis, saya selalu mencoba melakukan optimasi ini setelah aplikasi dalam keadaan aktif, dengan sebagian besar fitur sudah diimplementasikan. Jauh lebih mudah untuk fokus pada masalah kinerja ketika mereka benar-benar menghalangi.
Keterangan lebih lanjut
Komponen stateless fungsional:
Ini didefinisikan hanya menggunakan suatu fungsi. Karena tidak ada keadaan internal untuk komponen stateless, output (apa yang diberikan) hanya tergantung pada alat peraga yang diberikan sebagai input ke fungsi ini.
Pro:
Cara termudah untuk mendefinisikan komponen dalam Bereaksi. Jika Anda tidak perlu mengelola keadaan apa pun, mengapa repot-repot dengan kelas dan warisan? Salah satu perbedaan utama antara fungsi dan kelas adalah bahwa dengan fungsi Anda yakin output hanya bergantung pada input (bukan pada riwayat eksekusi sebelumnya).
Idealnya di aplikasi Anda, Anda harus bertujuan untuk memiliki komponen stateless sebanyak mungkin, karena itu biasanya berarti Anda memindahkan logika Anda di luar lapisan tampilan dan memindahkannya ke sesuatu seperti redux, yang berarti Anda dapat menguji logika Anda yang sebenarnya tanpa harus membuat apa pun. (lebih mudah untuk diuji, lebih dapat digunakan kembali, dll.).
Cons:
Tidak ada metode siklus hidup. Anda tidak memiliki cara untuk mendefinisikan componentDidMount
dan teman-teman lain. Biasanya Anda melakukannya dalam komponen induk yang lebih tinggi dalam hierarki sehingga Anda dapat mengubah semua anak menjadi yang tanpa kewarganegaraan.
Tidak ada cara untuk mengontrol secara manual saat diperlukan ulang, karena Anda tidak dapat menentukan shouldComponentUpdate
. Re-render terjadi setiap kali komponen menerima alat peraga baru (tidak ada cara untuk membandingkan dangkal, dll.). Di masa depan, Bereaksi dapat secara otomatis mengoptimalkan komponen stateless, untuk saat ini ada beberapa perpustakaan yang dapat Anda gunakan. Karena komponen stateless hanyalah fungsi, pada dasarnya ini adalah masalah klasik "memoisasi fungsi".
Referensi tidak didukung: https://github.com/facebook/react/issues/4936
Komponen yang memperluas kelas PureComponent VS Komponen normal yang memperluas kelas Komponen:
Bereaksi dulu, PureRenderMixin
Anda bisa melampirkan ke kelas yang ditentukan menggunakan React.createClass
sintaks. Mixin hanya akan mendefinisikan shouldComponentUpdate
melakukan perbandingan yang dangkal antara alat peraga berikutnya dan negara bagian berikutnya untuk memeriksa apakah ada perubahan di sana. Jika tidak ada yang berubah, maka tidak perlu melakukan render ulang.
Jika Anda ingin menggunakan sintaks ES6, Anda tidak bisa menggunakan mixin. Jadi untuk kenyamanan React memperkenalkan PureComponent
kelas yang bisa Anda warisi alih-alih menggunakan Component
. PureComponent
hanya mengimplementasikan shouldComponentUpdate
dengan cara yang sama PureRendererMixin
. Ini sebagian besar merupakan hal yang mudah sehingga Anda tidak perlu mengimplementasikannya sendiri, karena perbandingan yang dangkal antara kondisi saat ini / berikutnya dan alat peraga mungkin adalah skenario paling umum yang dapat memberi Anda beberapa kemenangan kinerja cepat.
Contoh:
class UserAvatar extends Component {
render() {
return <div><img src={this.props.imageUrl} /> {{ this.props.username }} </div>
}
}
Seperti yang Anda lihat, output tergantung pada props.imageUrl
dan props.username
. Jika dalam komponen induk Anda membuat <UserAvatar username="fabio" imageUrl="http://foo.com/fabio.jpg" />
dengan alat peraga yang sama, Bereaksi akan memanggil render
setiap waktu, bahkan jika output akan persis sama. Ingat juga bahwa React mengimplementasikan dom diffing, sehingga DOM tidak akan benar-benar diperbarui. Tetap saja, melakukan doming bisa mahal, jadi dalam skenario ini akan sia-sia.
Jika UserAvatar
komponen diperluas PureComponent
sebagai gantinya, dilakukan perbandingan dangkal. Dan karena alat peraga dan prop berikutnya adalah sama, render
tidak akan dipanggil sama sekali.
Catatan tentang definisi "murni" dalam Bereaksi:
Secara umum, "fungsi murni" adalah fungsi yang mengevaluasi selalu hasil yang sama diberikan input yang sama. Keluaran (untuk Bereaksi, itulah yang dikembalikan oleh render
metode) tidak bergantung pada riwayat / keadaan dan tidak memiliki efek samping (operasi yang mengubah "dunia" di luar fungsi).
Dalam Bereaksi, komponen stateless tidak harus komponen murni berdasarkan definisi di atas jika Anda memanggil "stateless" komponen yang tidak pernah memanggil this.setState
dan tidak digunakan this.state
.
Bahkan, dalam a PureComponent
, Anda masih bisa melakukan efek samping selama metode siklus hidup. Misalnya Anda dapat mengirim permintaan ajax di dalam componentDidMount
atau Anda bisa melakukan beberapa perhitungan DOM untuk secara dinamis menyesuaikan ketinggian div di dalam render
.
Definisi "Komponen bodoh" memiliki makna yang lebih "praktis" (setidaknya dalam pemahaman saya): komponen bodoh "diberitahu" apa yang harus dilakukan oleh komponen induk melalui alat peraga, dan tidak tahu bagaimana melakukan sesuatu tetapi menggunakan alat peraga panggilan balik sebagai gantinya.
Contoh dari "pintar" AvatarComponent
:
class AvatarComponent extends Component {
expandAvatar () {
this.setState({ loading: true });
sendAjaxRequest(...).then(() => {
this.setState({ loading: false });
});
}
render () {
<div onClick={this.expandAvatar}>
<img src={this.props.username} />
</div>
}
}
Contoh "bodoh" AvatarComponent
:
class AvatarComponent extends Component {
render () {
<div onClick={this.props.onExpandAvatar}>
{this.props.loading && <div className="spinner" />}
<img src={this.props.username} />
</div>
}
}
Pada akhirnya saya akan mengatakan bahwa "bodoh", "tanpa negara" dan "murni" adalah konsep yang sangat berbeda yang kadang-kadang bisa tumpang tindih, tetapi tidak harus, sebagian besar tergantung pada kasus penggunaan Anda.