Meningkatkan Fungsi Komponen Bereaksi dengan React.memo ()

Kami menyajikan kepada Anda terjemahan artikel oleh Chidume Nnamdi, yang diterbitkan di blog.bitsrc.io. Jika Anda ingin mempelajari cara menghindari render yang tidak perlu dan bagaimana alat baru berguna dalam Bereaksi, selamat datang di cat.



Tim React.js bekerja keras untuk membuat React berjalan secepat mungkin. Untuk memungkinkan pengembang mempercepat aplikasi Bereaksi mereka, alat berikut telah ditambahkan ke dalamnya:

  • React.lazy dan Suspense untuk keterlambatan memuat komponen;
  • Komponen murni
  • kait siklus hidup seharusnya memperbarui (...) {...}.

Pada artikel ini, kami akan mempertimbangkan, antara lain, alat pengoptimalan lain yang ditambahkan dalam React v16.6 untuk mempercepat fungsi komponen - React.memo .

Tip: Gunakan Bit untuk menginstal dan berbagi komponen Bereaksi. Gunakan komponen Anda untuk membangun aplikasi baru dan membaginya dengan tim untuk mempercepat. Cobalah!



Render ekstra


Dalam Bereaksi, setiap komponen terkait dengan unit tampilan. Komponen juga memiliki status. Ketika nilai status berubah karena tindakan pengguna, komponen menyadari bahwa menggambar ulang diperlukan. Komponen Bereaksi dapat digambar ulang beberapa kali. Dalam beberapa kasus, ini perlu, tetapi paling sering Anda dapat melakukannya tanpa renderer, terutama karena sangat memperlambat aplikasi.

Pertimbangkan komponen berikut:

import React from 'react'; class TestC extends React.Component { constructor(props) { super(props); this.state = { count: 0 } } componentWillUpdate(nextProps, nextState) { console.log('componentWillUpdate') } componentDidUpdate(prevProps, prevState) { console.log('componentDidUpdate') } render() { return ( <div > {this.state.count} <button onClick={()=>this.setState({count: 1})}>Click Me</button> </div> ); } } export default TestC; 

Nilai awal dari keadaan {count: 0} adalah 0. Jika Anda mengklik tombol Klik saya, status penghitungan akan menjadi 1. Di layar kami, 0 juga akan berubah menjadi 1. Tetapi jika kami mengklik tombol lagi, masalah mulai: komponen tidak boleh digambar ulang, karena kondisinya belum berubah. Nilai penghitung "ke" adalah 1, nilai baru juga satu, yang berarti bahwa tidak perlu memperbarui DOM.

Untuk melihat pembaruan TestC kami, di mana kondisi yang sama diatur dua kali, saya menambahkan dua metode siklus hidup. React memulai siklus componentWillUpdate ketika komponen diperbarui / digambar ulang karena perubahan status. ComponentdidUpdate React cycle dimulai ketika komponen berhasil dibuat.

Jika kami meluncurkan komponen di browser dan mencoba mengklik tombol Click me beberapa kali, kami mendapatkan hasil berikut:



Mengulangi entri componentWillUpdate di konsol kami menunjukkan bahwa komponen tersebut digambar ulang bahkan ketika keadaan tidak berubah. Ini adalah render tambahan.

Komponen Murni / harusPerbarui komponen


Kait siklus hidup shouldComponentUpdate akan membantu menghindari rendering yang tidak perlu dalam komponen Bereaksi.

React meluncurkan metode shouldComponentUpdate di awal rendering komponen dan menerima lampu hijau dari metode ini untuk melanjutkan proses atau sinyal bahwa proses terhambat .

Biarkan shouldComponentUpdate kami terlihat seperti ini:

 shouldComponentUpdate(nextProps, nextState) { return true } 

  • nextProps : nilai properti berikutnya yang akan diterima komponen;
  • nextState : nilai state selanjutnya yang akan diterima komponen.

Jadi kami mengizinkan Bereaksi untuk merender komponen karena nilai kembali true .

Misalkan kita menulis yang berikut ini:

 shouldComponentUpdate(nextProps, nextState) { return false } 

Dalam hal ini, kami melarang Bereaksi untuk membuat komponen, karena false dikembalikan.
Dari penjelasan di atas, untuk membuat komponen kita perlu mengembalikan true . Sekarang kita dapat menulis ulang komponen TestC sebagai berikut:

 import React from 'react'; class TestC extends React.Component { constructor(props) { super(props); this.state = { count: 0 } } componentWillUpdate(nextProps, nextState) { console.log('componentWillUpdate') } componentDidUpdate(prevProps, prevState) { console.log('componentDidUpdate') } shouldComponentUpdate(nextProps, nextState) { if (this.state.count === nextState.count) { return false } return true } render() { return ( <div> { this.state.count } <button onClick = { () => this.setState({ count: 1 }) }> Click Me </button> </div> ); } } export default TestC; 

Kami menambahkan pengait shouldComponentUpdate ke komponen TestC. Sekarang nilai count dalam objek keadaan saat ini this.state.count dibandingkan dengan nilai count dalam objek keadaan berikutnya nextState.count . Jika mereka sama === , menggambar ulang tidak terjadi dan false dikembalikan. Jika mereka tidak sama, true dikembalikan dan penyaji diluncurkan untuk menampilkan nilai baru.

Jika kami menguji kode di browser, kami akan melihat hasil yang familier:



Tetapi dengan mengklik tombol Click Me beberapa kali, yang kami lihat adalah yang berikut (hanya ditampilkan sekali!):

componentWillUpdate
componentDidUpdate




Anda dapat mengubah status komponen TestC di tab React DevTools. Klik pada tab React, pilih TestC di sebelah kanan, dan Anda akan melihat nilai status penghitung:



Nilai ini bisa diubah. Klik pada teks penghitung, ketik 2 dan tekan Enter.



Keadaan hitungan akan berubah, dan di konsol kita akan melihat:

 componentWillUpdate componentDidUpdate componentWillUpdate componentDidUpdate 



Nilai sebelumnya adalah 1, dan yang baru adalah 2, jadi redraw diperlukan.
Mari kita beralih ke Komponen Murni .

Komponen Murni muncul di Bereaksi dalam versi v15.5. Ini digunakan untuk membandingkan nilai standar ( change detection ). Menggunakan extend React.PureComponent , Anda tidak perlu menambahkan metode siklus hidup shouldComponentUpdate ke komponen: ubah pelacakan terjadi dengan sendirinya.

Tambahkan PureComponent ke komponen TestC.

 import React from 'react'; class TestC extends React.PureComponent { constructor(props) { super(props); this.state = { count: 0 } } componentWillUpdate(nextProps, nextState) { console.log('componentWillUpdate') } componentDidUpdate(prevProps, prevState) { console.log('componentDidUpdate') } /*shouldComponentUpdate(nextProps, nextState) { if (this.state.count === nextState.count) { return false } return true }*/ render() { return ( <div> { this.state.count } <button onClick = { () => this.setState({ count: 1 }) }> Click Me </button> </div > ); } } export default TestC; 

Seperti yang Anda lihat, kami shouldComponentUpdate ke dalam komentar. Kami tidak lagi membutuhkannya: semua pekerjaan dilakukan oleh React.PureComponent .

Mulai ulang browser untuk menguji solusi baru, dan mengklik tombol Click Me beberapa kali, kita dapatkan:





Seperti yang Anda lihat, hanya satu component*Update Entri component*Update muncul di konsol.

Setelah melihat bagaimana bekerja di Bereaksi dengan menggambar ulang di kelas komponen ES6, kami beralih ke fungsi komponen. Bagaimana cara mencapai hasil yang sama dengan mereka?

Komponen Fungsi


Kita sudah tahu bagaimana mengoptimalkan kerja dengan kelas menggunakan Komponen Murni dan shouldComponentUpdate siklus hidup shouldComponentUpdate . Tidak ada yang berpendapat bahwa komponen kelas adalah komponen utama Bereaksi, tetapi Anda dapat menggunakan fungsi sebagai komponen.

 function TestC(props) { return ( <div> I am a functional component </div> ) } 

Penting untuk diingat bahwa komponen fungsi, tidak seperti komponen kelas, tidak memiliki status (meskipun sekarang kait penggunaanState telah useState , ini dapat diperdebatkan dengan), yang berarti bahwa kita tidak dapat mengonfigurasi redrawingnya. Metode siklus hidup yang kami gunakan saat bekerja dengan kelas tidak tersedia bagi kami di sini. Jika kita dapat menambahkan kait siklus hidup ke komponen fungsi, kita dapat menambahkan metode shouldComponentUpdate untuk memberi tahu Bereaksi bahwa penyaji fungsi diperlukan. (Mungkin, dalam kalimat terakhir, penulis membuat kesalahan faktual. - Approx. Ed.) Dan, tentu saja, kita tidak bisa menggunakan extend React.PureComponent .

Kami mengubah kelas komponen kami ES6 TestC menjadi fungsi komponen.

 import React from 'react'; const TestC = (props) => { console.log(`Rendering TestC :` props) return ( <div> {props.count} </div> ) } export default TestC; // App.js <TestC count={5} /> 

Setelah rendering di konsol, kita melihat Rendering TestC :5 .



Buka DevTools dan klik pada tab React. Di sini kita akan mencoba mengubah nilai properti dari komponen TestC. Pilih TestC, dan properti penghitung dengan semua properti dan nilai TestC akan terbuka di sebelah kanan. Kami hanya melihat penghitung dengan nilai saat ini dari 5.

Klik pada angka 5 untuk mengubah nilainya. Jendela input akan muncul sebagai gantinya.



Jika kita mengubah nilai numerik dan menekan Enter, properti komponen akan berubah sesuai dengan nilai yang kita masukkan. Misalkan pada usia 45.



Buka tab Konsol.



Komponen TestC digambar ulang karena nilai sebelumnya dari 5 berubah menjadi yang sekarang - 45. Kembali ke tab Bereaksi dan ubah nilainya menjadi 45, kemudian kembali ke Konsol.



Seperti yang Anda lihat, komponen digambar ulang, meskipun nilai sebelumnya dan yang baru adalah sama. :(

Bagaimana cara mengelola penyaji?

Solusi: React.memo ()


React.memo() adalah fitur baru yang diperkenalkan di React v16.6. Prinsip operasinya mirip dengan prinsip React.PureComponent : membantu dalam mengelola React.PureComponent fungsi-komponen. React.memo(...) untuk komponen kelas adalah React.PureComponent untuk komponen fungsi.

Bagaimana cara kerja dengan React.memo (...)?
Cukup sederhana. Katakanlah kita memiliki fungsi komponen.

 const Funcomponent = ()=> { return ( <div> Hiya!! I am a Funtional component </div> ) } 

Kita hanya perlu meneruskan FuncComponent sebagai argumen ke fungsi React.memo.

 const Funcomponent = ()=> { return ( <div> Hiya!! I am a Funtional component </div> ) } const MemodFuncComponent = React.memo(FunComponent) 

React.memo mengembalikan MemodFuncComponent yang purified MemodFuncComponent . Inilah yang akan kita gambar di markup JSX. Ketika properti dan status komponen berubah, React membandingkan properti dan status komponen sebelumnya dan saat ini. Dan hanya jika mereka tidak identik, fungsi komponen digambar ulang.

Terapkan ini ke komponen fungsi TestC.

 let TestC = (props) => { console.log('Rendering TestC :', props) return ( <div> { props.count } </> ) } TestC = React.memo(TestC); 

Buka browser dan unduh aplikasi. Buka DevTools dan buka tab React. Pilih <Memo(TestC)> .

Jika di blok di sebelah kanan kami mengubah properti penghitung ke 89, aplikasi akan digambar ulang.



Jika kami mengubah nilai ke yang sebelumnya, 89, maka ...



Tidak akan ada penggambaran ulang!

Glory to React.memo (...)! :)

Tanpa menggunakan React.memo(...) dalam contoh pertama kami, fungsi komponen TestC digambar ulang bahkan ketika nilai sebelumnya berubah menjadi yang identik. Sekarang, terima kasih kepada React.memo(...) , kita dapat menghindari rendering fungsi komponen yang tidak perlu.

Kesimpulan


  • Mari kita lihat daftarnya?
  • React.PureComponent - perak;
  • React.memo(...) - emas;
  • React.PureComponent bekerja dengan kelas ES6;
  • React.memo(...) berfungsi dengan fungsi;
  • React.PureComponent mengoptimalkan gambar ulang kelas ES6;
  • React.memo(...) mengoptimalkan fungsi redrawing;
  • optimisasi fitur adalah ide yang hebat;
  • React tidak akan pernah sama lagi.

Jika Anda memiliki pertanyaan tentang artikel atau informasi tambahan, perubahan atau keberatan, jangan ragu untuk menulis komentar, email, atau pesan pribadi kepada saya.

Terima kasih

Source: https://habr.com/ru/post/id442116/


All Articles