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.
props
sama sekali. contoh .PureComponent
, Anda tidak harus menerapkanshouldComponentUpdate()
. Anda akan melihat peringatan jika Anda melakukan ini sebenarnya.PureComponent
komponen yang DO memiliki properti objek / array bersarang. Tentu saja Anda harus menyadari apa yang terjadi. Jika saya mengerti dengan benar, jika Anda tidak bermutasi secara langsung pada props / state (yang Bereaksi mencoba untuk mencegah Anda melakukan peringatan) atau melalui perpustakaan eksternal, maka Anda harus menggunakan dengan baikPureComponent
alih-alihComponent
cukup banyak di mana-mana ... dengan pengecualian komponen yang sangat sederhana di mana sebenarnya bisa lebih cepat TIDAK menggunakannya - lihat news.ycombinator.com/item?id=14418576Saya bukan jenius dalam bereaksi, tetapi dari pemahaman saya, kami dapat menggunakan setiap komponen dalam situasi berikut
Komponen stateless - ini adalah komponen yang tidak memiliki siklus hidup sehingga komponen-komponen tersebut harus digunakan dalam rendering elemen berulang komponen induk seperti rendering daftar teks yang hanya menampilkan informasi dan tidak memiliki tindakan untuk melakukan.
Komponen murni - ini adalah item yang memiliki siklus hidup dan mereka akan selalu mengembalikan hasil yang sama ketika satu set alat peraga tertentu diberikan. Komponen-komponen tersebut dapat digunakan ketika menampilkan daftar hasil atau data objek tertentu yang tidak memiliki elemen turunan yang kompleks dan digunakan untuk melakukan operasi yang hanya berdampak pada dirinya sendiri. seperti menampilkan daftar kartu pengguna atau daftar kartu produk (info produk dasar) dan hanya tindakan yang dapat dilakukan pengguna adalah mengklik untuk melihat halaman detail atau menambah ke keranjang.
Komponen Normal atau Komponen Kompleks - Saya menggunakan komponen kompleks karena biasanya komponen tingkat halaman dan terdiri dari banyak komponen anak-anak dan karena setiap anak dapat berperilaku dengan caranya sendiri yang unik sehingga Anda tidak dapat 100% yakin bahwa itu akan memberikan hasil yang sama pada kondisi yang diberikan. Seperti yang saya katakan biasanya ini harus digunakan sebagai komponen wadah
sumber
PureComponent
komponen tingkat dasar dan komponen di dekat bagian atas hierarki Anda biasanya di mana Anda akan melihat peningkatan kinerja terbesar. Tentu saja Anda perlu menghindari alat peraga yang bermutasi dan menyatakan secara langsung agar komponen murni berfungsi dengan benar, tetapi benda yang bermutasi secara langsung merupakan anti-pola dalam Bereaksi.React.Component
adalah komponen "normal" default. Anda mendeklarasikannya menggunakanclass
kata kunci danextends React.Component
. Pikirkan mereka sebagai kelas, dengan metode siklus hidup, penangan acara dan metode apa pun.React.PureComponent
adalahReact.Component
yang mengimplementasikanshouldComponentUpdate()
dengan fungsi yang melakukan perbandingan yang dangkalprops
danstate
. Anda harus menggunakanforceUpdate()
jika Anda tahu komponen memiliki alat peraga atau menyatakan data bersarang yang berubah dan Anda ingin merender ulang. Jadi mereka tidak hebat jika Anda membutuhkan komponen untuk dirender ulang ketika array atau objek yang Anda lewati sebagai alat peraga atau set di negara Anda berubah.Komponen fungsional adalah komponen yang tidak memiliki fungsi siklus hidup. Mereka seharusnya tanpa kewarganegaraan, tetapi mereka sangat bagus dan bersih sehingga kita sekarang memiliki kait (sejak Bereaksi 16.8) sehingga Anda masih dapat memiliki status. Jadi saya kira mereka hanya "komponen bersih".
sumber