Artikel ini meneroka komponen tanpa kerakyatan dalam React. Komponen jenis ini tidak mengandungi panggilan
this.state = { ... }
Komponen tanpa kerakyatan dalam React tidak mengandungi sebarang panggilan
this.state = { … }
Komponen tanpa kerakyatan boleh ditukar menjadi komponen fungsional, yang lebih seperti JavaScript tulen dan kurang ketergantungan pada rangka kerja yang digunakan. shouldComponentUpdate
Recompose adalah perpustakaan utiliti untuk komponen fungsi dan komponen lanjutan dalam React. Ia boleh digunakan untuk menjadikan komponen fungsi tanpa membuat semula apabila prop tidak berubah.
import React, { Component } from 'react' class User extends Component { render() { const { name, highlighted, userSelected } = this.props console.log('Hey User is being rendered for', [name, highlighted]) return <div> <h3 style={{fontStyle: highlighted ? 'italic' : 'normal'}} onClick={event => { userSelected() }}> {name} </h3> </div> } }
Kod berjalan secara normal. Ia sangat asas, tetapi ia membina contoh.
Perlu diperhatikan:
Ia tidak bertauliah, tanpa
this.state = { ... }
console.log
Pengendali acara di sini adalah "inline". Sintaks ini mudah kerana kodnya hampir dengan unsur -unsur yang diprosesnya, dan sintaks ini bermakna anda tidak perlu melakukan apa -apa .bind(this)
menggunakan fungsi sebaris sedemikian akan mempunyai sedikit kehilangan prestasi, kerana fungsi mesti dibuat setiap kali ia diberikan. Ini akan terperinci kemudian. sekarang kita menyedari bahawa komponen di atas bukan sahaja tanpa stat, ia sebenarnya adalah apa yang Dan Abramov memanggil komponen paparan. Ia hanya nama, tetapi pada dasarnya, ia ringan, menghasilkan beberapa HTML/DOM dan tidak mengendalikan sebarang data keadaan.
Jadi kita boleh membuatnya menjadi fungsi! Bukan sahaja ini terasa "sejuk", ia juga menjadikannya kurang mengerikan kerana lebih mudah difahami. Ia menerima input dan, secara bebas dari alam sekitar, sentiasa mengembalikan output yang sama. Sudah tentu, ia "panggilan balik" kerana salah satu alat peraga adalah fungsi yang boleh dipanggil.
mari kita menulis semula:
import React, { Component } from 'react' class User extends Component { render() { const { name, highlighted, userSelected } = this.props console.log('Hey User is being rendered for', [name, highlighted]) return <div> <h3 style={{fontStyle: highlighted ? 'italic' : 'normal'}} onClick={event => { userSelected() }}> {name} </h3> </div> } }
Rasanya baik, bukan? Rasanya seperti JavaScript tulen, anda boleh menulisnya tanpa memikirkan rangka kerja yang anda gunakan.
Masalah pengubahsuaian semula berterusan
Katakan komponen pengguna kami digunakan dalam komponen yang mengubah keadaan dari masa ke masa. Tetapi keadaan tidak menjejaskan komponen kita. Contohnya, seperti ini:
const User = ({ name, highlighted, userSelected }) => { console.log('Hey User is being rendered for', [name, highlighted]) return <div> <h3 style={{fontStyle: highlighted ? 'italic' : 'normal'}} onClick={event => { userSelected() }}> {name} </h3> </div> }
Jalankan kod ini dan anda akan melihat bahawa walaupun tiada perubahan, komponen kami akan diberikan semula! Ini bukan masalah besar sekarang, tetapi dalam aplikasi praktikal, komponen cenderung menjadi lebih dan lebih kompleks, dan setiap penanaman semula yang tidak perlu akan menyebabkan laman web melambatkan.
Jika anda menggunakan react-addons-perf
untuk menyahpepijat aplikasi ini sekarang, saya pasti anda akan mendapati masa itu dibazirkan pada rendering Users->User
. Alamak! Apa yang perlu dilakukan? !
Nampaknya segala -galanya menunjukkan bahawa kita perlu menggunakan shouldComponentUpdate
untuk menampung bagaimana reaksi berfikir prop berbeza, dan kita pasti mereka tidak berbeza. Untuk menambah cangkuk kitaran hayat React, komponen perlu menjadi kelas. Alas . Oleh itu, kami kembali ke pelaksanaan berasaskan kelas asal dan menambah kaedah cangkuk kitaran hayat baru:
Kembali ke Komponen Kelas
import React, { Component } from 'react' class Users extends Component { constructor(props) { super(props) this.state = { otherData: null, users: [{name: 'John Doe', highlighted: false}] } } async componentDidMount() { try { let response = await fetch('https://api.github.com') let data = await response.json() this.setState({otherData: data}) } catch(err) { throw err } } toggleUserHighlight(user) { this.setState(prevState => ({ users: prevState.users.map(u => { if (u.name === user.name) { u.highlighted = !u.highlighted } return u }) })) } render() { return <div> <h1>Users</h1> { this.state.users.map(user => { return <User name={user.name} highlighted={user.highlighted} userSelected={() => { this.toggleUserHighlight(user) }}/> }) } </div> } }
Perhatikan kaedah shouldComponentUpdate
yang baru ditambah. Ini agak hodoh. Bukan sahaja kita tidak lagi menggunakan fungsi, tetapi kita juga perlu menyenaraikan alat peraga secara manual yang boleh diubah. Ini melibatkan andaian berani bahawa prop fungsi userSelected
tidak akan berubah. Ini tidak mungkin, tetapi ia memerlukan perhatian.
Tetapi sila ambil perhatian bahawa walaupun komponen aplikasi yang disertakan semula, ini hanya akan diberikan sekali! Jadi, ini bagus untuk prestasi. Tetapi bolehkah kita melakukan yang lebih baik?
React.PureComponent
Sejak React 15.3, terdapat kelas asas komponen baru. Ia dipanggil PureComponent
, dan ia mempunyai kaedah terbina dalam shouldComponentUpdate
yang membuat "perbandingan cetek" setiap prop. Luar Biasa! Jika kita menggunakan ini, kita boleh membuang kaedah Custom shouldComponentUpdate
kita yang mesti menyenaraikan prop khusus.
import React, { Component } from 'react' class User extends Component { render() { const { name, highlighted, userSelected } = this.props console.log('Hey User is being rendered for', [name, highlighted]) return <div> <h3 style={{fontStyle: highlighted ? 'italic' : 'normal'}} onClick={event => { userSelected() }}> {name} </h3> </div> } }
cuba dan anda akan kecewa. Ia semula setiap kali. Kenapa? ! Jawapannya adalah kerana fungsi userSelected
dicipta semula setiap kali dalam kaedah render
aplikasi. Ini bermakna bahawa apabila komponen berasaskan PureComponent
memanggil sendiri shouldComponentUpdate()
, ia kembali true
, kerana fungsi itu sentiasa berbeza, kerana ia dicipta setiap kali.
Biasanya, penyelesaian kepada masalah ini adalah untuk mengikat fungsi dalam pembina yang mengandungi komponen. Pertama, jika kita melakukan ini, ini bermakna kita perlu menaip nama kaedah 5 kali (dan 1 sebelum):
this.userSelected = this.userSelected.bind(this)
(dalam pembina) userSelected() { ... }
(sebagai definisi kaedah itu sendiri) <User ... userSelected={this.userSelected} ... />
(di mana rendering komponen pengguna ditakrifkan) Satu lagi masalah ialah, seperti yang anda lihat, apabila kaedah userSelected
sebenarnya dilaksanakan, ia bergantung pada penutupan. Khususnya, ia bergantung kepada pembolehubah skop this.state.users.map()
dari iterator. user
untuk userSelected
dan kemudian apabila kaedah dipanggil (dalam komponen kanak -kanak), lulus this
(atau namanya ) kembali. Berikut adalah penyelesaian seperti ini. user
Kembali semula untuk menyelamatkan!
Pertama, mari kita semak matlamat kami:Menurut dokumentasi, rekomposnya adalah "Perpustakaan Alat Utiliti React untuk komponen fungsi dan komponen lanjutan. Fikirkannya sebagai lodash untuk React."
. Terdapat banyak untuk diterokai di perpustakaan ini, tetapi sekarang kami ingin menjadikan komponen fungsi kami tanpa membuat semula apabila alat peraga tidak berubah.Kali pertama kami cuba menulis semula kepada komponen fungsi dengan rekomposisi.pure, nampaknya ini:
import React, { Component } from 'react' class User extends Component { render() { const { name, highlighted, userSelected } = this.props console.log('Hey User is being rendered for', [name, highlighted]) return <div> <h3 style={{fontStyle: highlighted ? 'italic' : 'normal'}} onClick={event => { userSelected() }}> {name} </h3> </div> } }
dan
kekunci) tidak berubah.
name
mari kita melangkah lebih jauh. Kami tidak menggunakan highlighted
, tetapi kami menggunakan
, tetapi anda boleh menentukan kunci prop yang anda ingin fokus pada: recompose.pure
recompose.onlyUpdateForKeys
recompose.pure
const User = ({ name, highlighted, userSelected }) => { console.log('Hey User is being rendered for', [name, highlighted]) return <div> <h3 style={{fontStyle: highlighted ? 'italic' : 'normal'}} onClick={event => { userSelected() }}> {name} </h3> </div> }
atau
props berubah. Sekiranya komponen induknya diperuntukkan semula, komponen pengguna tidak.
name
Long live! Kami menjumpai emas! highlighted
Perbincangan
Pertama, tanya diri anda jika ia patut mengoptimumkan prestasi komponen anda. Mungkin itu lebih daripada itu. Komponen anda harus ringan, mungkin anda boleh memindahkan apa -apa pengiraan yang mahal daripada komponen dan memindahkannya ke fungsi yang tidak dapat dilupakan luaran, atau anda boleh menyusun semula komponen anda supaya sesetengah data tidak boleh membuang komponen rendering apabila digunakan. Sebagai contoh, dalam contoh ini, anda mungkin tidak mahu menjadikan komponen pengguna sebelum mengambilnya.
Menulis kod dengan cara yang paling mudah untuk anda, kemudian memulakan program anda dan melangkah dari sana untuk menjadikannya lebih baik bukan penyelesaian yang buruk. Dalam contoh ini, untuk meningkatkan prestasi, anda perlu menentukan komponen fungsi dari:
import React, { Component } from 'react' class User extends Component { render() { const { name, highlighted, userSelected } = this.props console.log('Hey User is being rendered for', [name, highlighted]) return <div> <h3 style={{fontStyle: highlighted ? 'italic' : 'normal'}} onClick={event => { userSelected() }}> {name} </h3> </div> } }
... ditukar kepada ...
const User = ({ name, highlighted, userSelected }) => { console.log('Hey User is being rendered for', [name, highlighted]) return <div> <h3 style={{fontStyle: highlighted ? 'italic' : 'normal'}} onClick={event => { userSelected() }}> {name} </h3> </div> }
Sebaik -baiknya, bukannya menunjukkan cara untuk memintas masalah, penyelesaian terbaik adalah patch baru dari React, yang membuat peningkatan yang besar kepada shallowEqual
untuk "secara automatik" mengenal pasti masuk dan membandingkan adalah fungsi, dan hanya kerana Ia tidak sama tidak bermakna bahawa ia sebenarnya berbeza.
setuju! Terdapat alternatif kompromi untuk berurusan dengan fungsi sebaris yang mengikat kaedah dalam pembina dan setiap rekreasi. Itulah bidang kelas awam. Ia adalah ciri Fasa 2 di Babel, jadi persediaan anda mungkin akan menyokongnya. Sebagai contoh, di sini adalah cawangan yang menggunakannya, yang bukan sahaja lebih pendek, tetapi sekarang juga bermakna kita tidak perlu menyenaraikan semua alat bukan fungsi secara manual. Penyelesaian ini mesti meninggalkan penutupan. Walau bagaimanapun, masih bagus untuk mengetahui dan menyedari recompose.onlyUpdateForKeys
apabila diperlukan.
Untuk maklumat lanjut mengenai React, sila lihat kursus kami "React the ES6 Way".
Artikel ini telah dikaji semula oleh Jack Franklin. Terima kasih kepada semua pengulas rakan sebaya untuk membuat kandungan SitePoint sempurna!
soalan yang sering ditanya mengenai mengoptimumkan prestasi reaksi dengan komponen tanpa stat. Apakah perbezaan utama antara komponen negara dan komponen tanpa statistik dalam React?
Bagaimana untuk mengoptimumkan prestasi aplikasi React saya menggunakan komponen tanpa kerakyatan?
PureComponent
adalah komponen reaksi khas yang membantu mengoptimumkan prestasi aplikasi anda. Ia menggunakan perbandingan prop dan negara cetek untuk melaksanakan kaedah shouldComponentUpdate
kitaran hayat. Ini bermakna ia akan membuat semula hanya apabila keadaan atau props berubah, yang dapat mengurangkan penampilan semula yang tidak perlu dan meningkatkan prestasi.
Menukar komponen negeri ke komponen tanpa kewarganegaraan termasuk mengeluarkan kaedah negeri atau kitaran hayat dari komponen. Komponen hanya perlu menerima data melalui alat peraga dan menjadikannya. Berikut adalah contoh:
// komponen status Kelas Selamat Datang memanjangkan React.Component { render () { kembali
// komponen tanpa stat fungsi selamat datang (props) { kembali
Beberapa amalan terbaik untuk menggunakan komponen tanpa statistik dalam React termasuk: Gunakan seberapa banyak yang mungkin untuk meningkatkan prestasi dan kebolehbacaan; Ia juga disyorkan untuk menggunakan dekonstruksi prop untuk menulis kod bersih.
Tidak, komponen tanpa kerakyatan tidak boleh menggunakan kaedah kitaran hayat dalam React. Kaedah kitaran hayat hanya boleh digunakan untuk komponen kelas. Walau bagaimanapun, dengan pengenalan cangkuk dalam React 16.8, kini anda boleh menambah ciri -ciri keadaan dan kitaran hayat untuk berfungsi komponen.
Walaupun komponen tanpa kerakyatan mempunyai banyak kelebihan, mereka juga mempunyai beberapa batasan. Mereka tidak boleh menggunakan kaedah kitaran hayat atau menguruskan keadaan mereka sendiri. Walau bagaimanapun, batasan -batasan ini dapat diatasi dengan menggunakan cangkuk Reacts.
Komponen tanpa statik meningkatkan kebolehbacaan kod melalui kesederhanaan dan kejelasan. Mereka tidak menguruskan keadaan mereka sendiri atau menggunakan kaedah kitaran hayat, yang menjadikannya lebih mudah dan mudah difahami. Mereka juga menggalakkan penggunaan komponen kecil dan boleh diguna semula, yang boleh menjadikan kod lebih teratur dan lebih mudah untuk dikekalkan.
Ya, komponen tanpa kerakyatan boleh mengendalikan peristiwa dalam React. Pengendali acara boleh diluluskan sebagai alat peraga kepada komponen tanpa stat. Berikut adalah contoh:
fungsi ActionLink (props) { Kembali ( Klik saya ); }
Komponen tanpa statik mempromosikan modularization kod dengan mempromosikan penggunaan komponen kecil dan boleh diguna semula. Setiap komponen boleh dibangunkan dan diuji secara bebas, yang menjadikan kod lebih mudah untuk dikekalkan dan difahami. Ia juga menggalakkan pemisahan kebimbangan, di mana setiap komponen bertanggungjawab untuk satu fungsi.
Atas ialah kandungan terperinci Mengoptimumkan prestasi bertindak balas dengan komponen tanpa statistik. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!