Perang rem. Mengoptimalkan jumlah rendering komponen di React Native

Halo, Habr! Nama saya Kamo Spertsyan, saya terlibat dalam pengembangan React Native di Profi.ru. Jika Anda memutuskan untuk menggunakan teknologi React Native untuk secara cepat menghadirkan fitur produk dan fokus pada kecepatan pengembangan, maka Anda kemungkinan akan mengalami masalah kinerja. Setidaknya itulah yang terjadi pada kita. Setelah enam bulan pengembangan aktif, kinerja aplikasi kami turun di bawah tingkat kritis - semuanya sangat lambat. Karena itu, kami melakukan optimasi - menghapus semua "rem" saat startup, transisi di antara layar, merender layar, reaksi terhadap tindakan pengguna. Hasilnya, dalam tiga bulan mereka membawa pengalaman pengguna ke tingkat asli. Pada artikel ini saya ingin berbicara tentang bagaimana kami mengoptimalkan aplikasi pada React Native dan menyelesaikan masalah render banyak komponen.



Saya mengumpulkan rekomendasi yang akan membantu meminimalkan jumlah redraws komponen yang tidak berguna. Untuk kejelasan, dalam contoh saya membandingkan implementasi "buruk" dan "baik". Artikel ini akan bermanfaat bagi mereka yang sudah dihadapkan dengan kinerja aplikasi yang buruk, dan mereka yang tidak ingin mengizinkan ini di masa depan.

Kami menggunakan Bereaksi Asli yang dipasangkan dengan Redux. Beberapa tips terkait dengan perpustakaan ini. Juga dalam contoh, saya menggunakan pustaka Redux-thunk - untuk mensimulasikan bekerja dengan jaringan.

Kapan memikirkan kinerja?


Bahkan, perlu diingat sejak awal bekerja pada aplikasi. Tetapi jika aplikasi Anda sudah melambat - jangan putus asa, semuanya bisa diperbaiki.

Semua orang tahu, tetapi untuk berjaga-jaga, saya akan menyebutkan: lebih baik untuk memeriksa kinerja pada perangkat yang lemah. Jika Anda mengembangkan pada perangkat yang kuat, Anda mungkin tidak menyadari "rem" dari pengguna akhir. Tentukan sendiri perangkat yang akan Anda pandu. Ukur waktu atau FPS dalam plot kontrol untuk membandingkan dengan hasil setelah optimasi.

Bereaksi Asli di luar kotak menyediakan kemampuan untuk mengukur aplikasi FPS melalui Alat Pengembang โ†’ Tampilkan monitor perf. Nilai referensi adalah 60 frame per detik. Semakin rendah indikator ini, semakin kuat aplikasi "melambat" - tidak merespons atau bereaksi dengan penundaan terhadap tindakan pengguna. Salah satu efek utama pada FPS adalah jumlah render, "keparahan" yang tergantung pada kompleksitas komponen.

Deskripsi contoh


Saya menunjukkan semua rekomendasi pada contoh aplikasi sederhana dengan daftar berita. Aplikasi ini memiliki satu layar, yang terletak FlatListdengan berita. Item berita adalah komponen NewsItemyang terdiri dari dua komponen yang lebih kecil - informasi utama ( NewsItemTitle) dan tubuh ( NewsItemBody). Seluruh contoh bisa dilihat di sini . Lebih lanjut dalam teks adalah tautan ke berbagai cabang repositori untuk contoh spesifik. Repositori digunakan untuk kenyamanan pembaca yang ingin menjelajahi contoh lebih dalam. Kode dalam repositori dan contoh di bawah ini tidak mengklaim sebagai sempurna - hanya diperlukan untuk tujuan demonstrasi.

Di bawah ini, semua komponen ditampilkan secara skematis dengan tautan dan alat peraga.


Dalam metode render setiap komponen, saya menambahkan output ke konsol informasi unik tentangnya:

SCREEN
ITEM_{no}
ITEM_TITLE_{no}
ITEM_BODY_{no}

di mana {no}adalah nomor seri berita untuk membedakan antara renderings berita yang berbeda dari beberapa rendering yang sama.

Untuk pengujian pada setiap refreshdaftar berita, berita tambahan ditambahkan ke awal. Pada saat yang sama, pesan berikut ini ditampilkan di konsol:

--------------[ REFRESHING ]--------------

Catatan-catatan ini akan membantu untuk memahami jika ada masalah dalam komponen tertentu, dan kemudian untuk menentukan apakah mungkin untuk mengoptimalkannya.

Jika diterapkan dengan benar, log kami setelah peluncuran dan beberapa pembaruan akan terlihat seperti ini:

SCREEN
ITEM_2
ITEM_TITLE_2
ITEM_BODY_2
ITEM_1
ITEM_TITLE_1
ITEM_BODY_1
--------------[ REFRESHING ]--------------
SCREEN
ITEM_3
ITEM_TITLE_3
ITEM_BODY_3
--------------[ REFRESHING ]--------------
SCREEN
ITEM_4
ITEM_TITLE_4
ITEM_BODY_4

Pada awal pertama, layar itu sendiri dan dua berita awal diambil. Saat memperbarui papan, layar ditampilkan lagi, karena datanya telah benar-benar berubah. Lebih banyak berita muncul. Semua berita sebelumnya tidak digambar ulang, karena tidak ada perubahan dalam data mereka.

Kapan komponen diberikan?


Dalam Bereaksi dan Bereaksi Asli, ada dua kondisi untuk merender komponen:

  1. mengubah props / kondisinya,
  2. membuat komponen induk.

Suatu fungsi dapat didefinisikan ulang dalam suatu komponen shouldComponentUpdate- ia menerima Alat Peraga dan Status baru sebagai input dan memberi tahu apakah komponen tersebut harus dirender. Seringkali, untuk menghindari render yang tidak perlu, perbandingan yang dangkal dari Alat Peraga dan objek Negara sudah cukup. Misalnya, ini menghilangkan render yang tidak perlu ketika komponen induk berubah, jika mereka tidak mempengaruhi komponen turunan. Agar tidak menulis perbandingan permukaan secara manual setiap kali, Anda bisa mewarisi komponen dari React.PureComponentyang merangkum pemeriksaan ini.

Ketika kami menggunakan fungsi tautan hubung, pustaka Redux membuat komponen baru yang "terhubung" ke Negara global. Perubahan pada status ini memicu suatu metodemapStateToPropsyang mengembalikan alat peraga baru. Selanjutnya, perbandingan alat peraga lama dan baru dimulai, terlepas dari apakah komponen dinyatakan sebagai PureComponentatau tidak.

Pertimbangkan nuansa ini dalam contoh kita.

Kami akan NewsItemmembiarkan komponen melewati connect, NewsItemTitlemewarisi dari React.Component, dan NewsItemBody- dari React.PureComponent.

โ†’ Kode contoh lengkap

export class NewsItemTitle extends React.Component
export class NewsItemBody extends React.PureComponent

Berikut ini tampilan log setelah pembaruan satu papan:

SCREEN
ITEM_2
ITEM_TITLE_2
ITEM_BODY_2
ITEM_1
ITEM_TITLE_1
ITEM_BODY_1
--------------[ REFRESHING ]--------------
SCREEN
ITEM_3
ITEM_TITLE_3
ITEM_BODY_3
ITEM_2
ITEM_TITLE_2
ITEM_1
ITEM_TITLE_1

Anda dapat melihat bahwa komponen berita dan informasi utama digambar ulang. Kami akan mempertimbangkan mereka pada gilirannya.

NewsItemdideklarasikan menggunakan connect. Sebagai alat peraga, komponen ini menerima pengidentifikasi, yang kemudian menerima berita di mapStateToProps:

const mapStateToProps = (state, ownProps) => ({
  item: state.newsMap[ownProps.itemKey],
});

Karena ketika memperbarui papan semua berita diunduh lagi, objek akan itemmemperbarui dan kemudian akan merujuk ke berbagai sel memori. Dengan kata lain, mereka akan menjadi objek yang berbeda, bahkan jika semua bidang yang ada adalah sama. Oleh karena itu, perbandingan pengembalian State'ov komponen sebelumnya dan baru false. Komponen akan dirender ulang, meskipun faktanya data tidak berubah.

NewsItemTitlediwarisi dari React.Component, sehingga dirender ulang setiap kali komponen induk dirender. Ini terjadi terlepas dari nilai alat peraga lama dan baru.

NewsItemBodydiwarisi dari React.PureComponent, sehingga membandingkan alat peraga lama dan baru. Dalam berita 1 dan 2, nilainya setara, oleh karena itu komponen ini diberikan hanya untuk berita 3.

Untuk mengoptimalkan renderingNewsItemTitlecukup nyatakan sebagai React.PureComponent. Dalam hal ini, Anda harus NewsItemmendefinisikan kembali fungsi shouldComponentUpdate:

shouldComponentUpdate(nextProps) {
  return !shallowEqual(this.props.item, nextProps.item);
}

โ†’ Kode contoh lengkap

Berikut shallowEqualadalah fitur untuk perbandingan permukaan objek yang disediakan Redux. Anda dapat menulis seperti ini:

shouldComponentUpdate(nextProps) {
  return (
    this.props.item.title !== nextProps.item.title ||
    this.props.item.body !== nextProps.item.body
  );
}

Beginilah tampilan log kami setelah ini:

SCREEN
ITEM_2
ITEM_TITLE_2
ITEM_BODY_2
ITEM_1
ITEM_TITLE_1
ITEM_BODY_1
--------------[ REFRESHING ]--------------
SCREEN
ITEM_3
ITEM_TITLE_3
ITEM_BODY_3

Catatan
shouldComponentUpdate NewsItem , NewsItemTitle . . NewsItemTitle - NewsItem, .

React.memo dan komponen fungsional


Tidak shouldComponentUpdatemungkin menimpa komponen fungsional. Tetapi ini tidak berarti bahwa untuk mengoptimalkan komponen fungsional, Anda harus menulis ulang menjadi kelas satu. Untuk kasus seperti itu, fungsi memoisasi React.memo disediakan . Ini menerima input komponen dan fungsi perbandingan opsional areEqual. Saat dipanggil, alat ini areEqualmenjadi tua dan baru dan harus mengembalikan hasil perbandingan. Bedanya dengan shouldComponentUpdateapa yang areEqualharus dikembalikan truejika propsnya sama, dan bukan sebaliknya.

Misalnya, NewsItemTitlememoisasi mungkin terlihat seperti ini:

areEqual(prevProps, nextProps) {
  return shallowEqual(prevProps, nextProps);
}
export OptimizedNewsItemTitle = React.memo(NewsItemTitle, areEqual)

Jika Anda tidak lulus areEqualdalam React.memo, maka perbandingan dangkal alat peraga akan dibuat, sehingga contoh kita dapat disederhanakan:

export OptimizedNewsItemTitle = React.memo(NewsItemTitle)

Fungsi Lambda dalam alat peraga


Untuk memproses peristiwa komponen, fungsi dapat diteruskan ke alat peraga. Contoh yang paling mencolok adalah implementasi onPress. Seringkali fungsi lambda anonim digunakan untuk ini. Katakanlah NewsItemBodykita hanya ingin menampilkan pratinjau, dan jika Anda mengkliknya - seluruh teks. Untuk melakukan ini, ketika merender NewsItem, NewsItemBodykami akan melewati prop berikut:

<NewsItemBody
  ...
  onPress={() => this.props.expandBody()}
  ...
/>

Seperti inilah tampilan log dengan implementasi ini ketika metode shouldComponentUpdateini NewsItemdihapus:

SCREEN
ITEM_2
ITEM_TITLE_2
ITEM_BODY_2
ITEM_1
ITEM_TITLE_1
ITEM_BODY_1
--------------[ REFRESHING ]--------------
SCREEN
ITEM_3
ITEM_TITLE_3
ITEM_BODY_3
ITEM_2
ITEM_TITLE_2
ITEM_BODY_2
ITEM_1
ITEM_TITLE_1
ITEM_BODY_1

Berita badan 1 dan 2 tersebut diberikan, walaupun data mereka tidak berubah, tetapi NewsItemBodyadalah PureComponent. Ini disebabkan oleh fakta bahwa untuk setiap render NewsItemnilai alat peraga onPressdibuat baru. Secara teknis, onPressdengan setiap render, ini menunjuk ke area baru dalam memori, jadi perbandingan yang tidak proporsional dari alat peraga dalam NewsItemBodypengembalian salah. Masalahnya diperbaiki oleh entri berikut:

<NewsItemBody
  ...
  onPress={this.props.expandBody}
  ...
/>

Catatan:

SCREEN
ITEM_2
ITEM_TITLE_2
ITEM_BODY_2
ITEM_1
ITEM_TITLE_1
ITEM_BODY_1
--------------[ REFRESHING ]--------------
SCREEN
ITEM_3
ITEM_TITLE_3
ITEM_BODY_3
ITEM_2
ITEM_TITLE_2
ITEM_1
ITEM_TITLE_1

โ†’ Kode contoh lengkap

Sayangnya, fungsi anonim tidak dapat selalu ditulis ulang sebagai metode atau bidang kelas untuk catatan semacam itu. Kasus yang paling umum adalah ketika di dalam fungsi lambda, variabel ruang lingkup fungsi yang dideklarasikan digunakan.

Pertimbangkan kasus ini dalam contoh kita. Untuk beralih dari daftar umum ke layar satu berita, kami menambahkan proses mengklik pada badan berita. Metode renderItemkomponen FlatListakan terlihat seperti ini:

const renderItem = ({item}) => (
  <NewsItem
    itemKey={item}
    onBodyPress={() => this.onItemBodyPress(item)}
  />
);

Fungsi anonim onBodyPresstidak dapat dideklarasikan di kelas, karena variabel itemyang diperlukan untuk pergi ke berita tertentu akan hilang dari ruang lingkup .

Solusi paling sederhana untuk masalah ini adalah dengan mengubah tanda tangan onBodyPresskomponen alat peraga NewsItemsehingga parameter yang diperlukan diteruskan ke fungsi saat dipanggil. Dalam hal ini, ini adalah pengidentifikasi berita.

const renderItem = ({item}) => (
  <NewsItem
    itemKey={item}
    onBodyPress={item => this.onItemBodyPress(item)}
  />
);

Dalam hal ini, kita sudah dapat menghapus fungsi anonim dalam metode kelas komponen.

const renderItem = ({item}) => (
  <NewsItem
    itemKey={item}
    onBodyPress={this.onItemBodyPress}
  />
);

Namun, solusi seperti itu akan mengharuskan kita untuk mengubah komponen NewsItem.

class NewsItemComponent extends React.Component {
render() {
  ...
  return (
      ...
      <NewsItemBody
        ...
        onPress={() => this.props.onBodyPress(this.props.item)}
        ...
      />
      ...
  );
}

Dan lagi kita kembali ke masalah yang ditunjukkan - kita melewati fungsi lambda baru ke komponen anak untuk setiap render dari orang tua. Baru sekarang kita turun satu tingkat. Catatan:

SCREEN
ITEM_2
ITEM_TITLE_2
ITEM_BODY_2
ITEM_1
ITEM_TITLE_1
ITEM_BODY_1
--------------[ REFRESHING ]--------------
SCREEN
ITEM_3
ITEM_TITLE_3
ITEM_BODY_3
ITEM_2
ITEM_TITLE_2
ITEM_BODY_2
ITEM_1
ITEM_TITLE_1
ITEM_BODY_1

Untuk menghilangkan masalah ini di root, Anda dapat menggunakan hook useCallback . Hal ini memungkinkan Anda untuk mem memanggil panggilan fungsi dengan menyampaikan argumen. Jika argumen fungsi tidak berubah, maka hasil panggilan useCallbackakan menunjuk ke area memori yang sama. Dalam contoh kami, ini berarti bahwa ketika menggambar ulang berita yang sama, onPresskomponen prop NewsItemBodytidak akan berubah. Kait hanya dapat digunakan dalam komponen fungsional, sehingga tampilan akhir komponen NewsItemadalah sebagai berikut:

function NewsItemComponent(props) {
  ...
  const {itemKey, onBodyPress} = props.item;
  const onPressBody = useCallback(() => onBodyPress(itemKey), [itemKey, onBodyPress]);
  return (
    <View>
      ...
      <NewsItemBody
        ...
        onPress={onPressBody}
        ...
      />
    </View>
  );
}

Dan log:

SCREEN
ITEM_2
ITEM_TITLE_2
ITEM_BODY_2
ITEM_1
ITEM_TITLE_1
ITEM_BODY_1
--------------[ REFRESHING ]--------------
SCREEN
ITEM_3
ITEM_TITLE_3
ITEM_BODY_3
ITEM_2
ITEM_TITLE_2
ITEM_1
ITEM_TITLE_1

โ†’ Kode contoh lengkap

Array dan objek


Dalam JavaScript, fungsi direpresentasikan sebagai objek, bersama dengan array. Oleh karena itu, contoh dari blok sebelumnya adalah kasus khusus untuk membuat objek baru di alat peraga. Ini cukup umum, jadi saya letakkan di paragraf terpisah.

Setiap penciptaan fungsi, array, atau objek baru dalam props mengarah ke re-renderer komponen. Pertimbangkan aturan ini dalam contoh berikut. Mari kita berikan NewsItemBodygaya gabungan dari dua nilai:

<NewsItemBody
  ...
  style={[styles.body, styles.item]}
  ...
/>

Dan lagi, log menunjukkan penyaji komponen tambahan:

SCREEN
ITEM_2
ITEM_TITLE_2
ITEM_BODY_2
ITEM_1
ITEM_TITLE_1
ITEM_BODY_1
--------------[ REFRESHING ]--------------
SCREEN
ITEM_3
ITEM_TITLE_3
ITEM_BODY_3
ITEM_2
ITEM_TITLE_2
ITEM_BODY_2
ITEM_1
ITEM_TITLE_1
ITEM_BODY_1

Untuk mengatasi masalah ini, Anda dapat memilih gaya terpisah yang akan menggabungkan bodydan item, atau, misalnya, memindahkan deklarasi array [styles.body, styles.item]ke variabel global.

โ†’ Kode contoh lengkap

Reduksi array


Pertimbangkan sumber "rem" populer lain yang terkait dengan penggunaan FlatList. Aplikasi klasik yang berisi daftar panjang item dari server mengimplementasikan pagination. Yaitu, ia memuat serangkaian elemen terbatas dalam bentuk halaman pertama, ketika daftar elemen saat ini berakhir, ia memuat halaman berikutnya, dan seterusnya. Peredam daftar item mungkin terlihat seperti ini:

const newsIdList = (state = [], action) => {
  if (action.type === 'GOT_NEWS') {
    return action.news.map(item => item.key);
  } else if (action.type === 'GOT_OLDER_NEWS') {
    return [...state, ...action.news.map(item => item.key)];
  }
  return state;
};

Ketika setiap halaman berikutnya memuat gaya aplikasi, array pengidentifikasi baru dibuat. Jika kita meneruskan array ini ke alat peraga nanti FlatList, inilah tampilan komponen render log:

SCREEN
ITEM_<1..10>
--------------[ LOADING NEXT PAGE ]--------------
SCREEN
ITEM_<1..10>
ITEM_<1..20>
--------------[ LOADING NEXT PAGE ]--------------
SCREEN
ITEM_<1..20>
ITEM_<1..30>

Untuk contoh ini, saya membuat beberapa perubahan pada aplikasi pengujian.

  • Atur ukuran halaman menjadi 10 berita.
  • item NewsItem FlatList-, connect. NewsItem React.Component .
  • .
  • . โ„–1 .

Contoh menunjukkan bahwa ketika setiap halaman berikutnya memuat, semua elemen lama dirender lagi, maka elemen lama dan elemen-elemen halaman baru dirender lagi. Untuk pecinta matematika: jika ukuran halaman sama X, maka ketika ihalaman ke - i dimuat, alih-alih hanya merender Xelemen baru, elemen tersebut dirender (i - 1) * X + i * X.

โ€œOke,โ€ Anda berkata, โ€œSaya mengerti mengapa semua elemen digambar setelah menambahkan halaman baru: peredam mengembalikan array baru, area memori baru, semuanya. Tetapi mengapa kita perlu membuat daftar lama sebelum menambahkan elemen baru? " "Pertanyaan bagus," aku akan menjawabmu. Ini adalah konsekuensi dari bekerja dengan keadaan komponen VirtualizedListatas dasar siapaFlatList. Saya tidak akan merinci, karena mereka menarik artikel yang terpisah. Siapa yang peduli, saya sarankan Anda mempelajari dokumentasi dan sumbernya.

Bagaimana cara menghilangkan non-optimalitas seperti itu? Kami menulis ulang peredam sehingga ia tidak mengembalikan array baru untuk setiap halaman, tetapi menambahkan elemen ke yang sudah ada:

Perhatian! Antipattern!
. , , , PureComponent, . , . . Redux.

const newsIdList = (state = [], action) => {
  if (action.type === 'GOT_NEWS') {
    return action.news.map(item => item.key);
  } else if (action.type === 'GOT_OLDER_NEWS') {
    action.news.forEach(item => state.push(item.key));
    return state;
    // return [...state, ...action.news.map(item => item.key)];
  }
  return state;
};

Setelah itu, log kita akan terlihat seperti ini:

SCREEN
ITEM_<1..10>
--------------[ LOADING NEXT PAGE ]--------------
SCREEN
ITEM_<1..20>
--------------[ LOADING NEXT PAGE ]--------------
SCREEN
ITEM_<1..30>

Kami menyingkirkan rendering elemen lama sebelum menambahkan elemen ke halaman baru, tetapi elemen lama masih digambar setelah memperbarui daftar. Jumlah rendering untuk halaman berikutnya sekarang sama i * X. Rumusnya menjadi lebih sederhana, tetapi kami tidak akan berhenti di situ. Kami hanya memiliki Xelemen baru, dan kami hanya ingin Xrender baru. Kami akan menggunakan trik yang sudah biasa untuk menghapus render berita yang belum mengubah alat peraga. Kembali terhubung ke NewsItem:

SCREEN
ITEM_<1..10>
--------------[ LOADING NEXT PAGE ]--------------
SCREEN
ITEM_<11..20>
--------------[ LOADING NEXT PAGE ]--------------
SCREEN
ITEM_<21..30>

Baik! Sekarang kita bisa puas dengan diri kita sendiri. Tidak ada tempat untuk mengoptimalkan.

โ†’ Kode contoh lengkap

Pembaca yang penuh perhatian akan menunjukkan bahwa setelah menerapkan koneksi ke NewsItemlog, akan terlihat seperti pada contoh terakhir, tidak peduli bagaimana Anda mengimplementasikan peredam. Dan itu akan benar - jika komponen berita memeriksa properti sebelum rendering, tidak masalah apakah array lama digunakan oleh reducer atau membuat yang baru. Hanya elemen baru yang digambar dan hanya sekali. Namun, mengubah array lama bukannya membuat yang baru menyelamatkan kita dari rendering komponen yang tidak perlu yang FlatListdigunakan di dalamnya VirtualizedListdan iterasi yang tidak perlu dari pemeriksaan ekuivalen alat peraga NewsItem. Dengan sejumlah besar elemen, ini juga memberikan peningkatan kinerja.

Gunakan array dan objek yang bisa berubah dalam reduksi harus dengan sangat hati-hati. Dalam contoh ini, ini dibenarkan, tetapi jika Anda memiliki, katakanlah, normal PureComponent, maka ketika Anda menambahkan elemen ke array yang bisa berubah, komponen tidak akan dirender. Alat peraga pada kenyataannya tetap tidak berubah, karena sebelum dan sesudah memperbarui titik-titik array ke area memori yang sama. Ini dapat menyebabkan konsekuensi yang tidak terduga. Tidak heran contoh yang dijelaskan itu melanggar prinsip - prinsip Redux .

Dan sesuatu yang lain ...


Jika Anda menggunakan perpustakaan tingkat presentasi, saya menyarankan Anda untuk memastikan bahwa Anda memahami secara detail bagaimana mereka diterapkan. Dalam aplikasi kami, kami menggunakan komponen Swipeabledari perpustakaan react-native-gesture-handler. Ini memungkinkan Anda untuk menerapkan blok tindakan tambahan saat menggesek kartu dari daftar.

Dalam kode, tampilannya seperti ini:

<Swipeable
  ...
  renderRightActions={this.renderRightActions}
  ...
>

Metode renderRightActionsatau renderLeftActionsmengembalikan komponen yang ditampilkan setelah gesek. Kami menentukan dan mengubah ketinggian panel selama pergantian komponen agar sesuai dengan konten yang diperlukan. Ini adalah proses yang intensif sumber daya, tetapi jika itu terjadi selama animasi swipe, pengguna tidak melihat gangguan.


Masalahnya adalah bahwa komponen Swipeablememanggil metode renderRightActionspada saat rendering komponen utama. Semua perhitungan dan bahkan rendering pada bilah tindakan, yang tidak terlihat sebelum gesekan, terjadi di muka. Jadi, semua tindakan ini dilakukan untuk semua kartu dalam daftar secara bersamaan. Ini menyebabkan "rem" yang signifikan saat menggulir papan.

Masalahnya dipecahkan dengan cara berikut. Jika panel tindakan ditarik bersama-sama dengan komponen utama, dan bukan sebagai akibat dari gesek, maka metode renderRightActionsmengembalikan yang kosong Viewukuran komponen utama. Kalau tidak, kami menggambar panel tindakan tambahan seperti sebelumnya.
Saya memberikan contoh ini karena perpustakaan pendukung tidak selalu berfungsi seperti yang Anda harapkan. Dan jika ini adalah perpustakaan tingkat presentasi, maka lebih baik untuk memastikan bahwa mereka tidak membuang sumber daya yang tidak perlu.

temuan


Setelah menghilangkan masalah yang dijelaskan dalam artikel, kami secara signifikan mempercepat aplikasi pada React Native. Sekarang sulit untuk membedakannya dalam kinerja dari yang serupa, dilaksanakan secara asli. Kelebihan render memperlambat pemuatan layar individual dan reaksi terhadap tindakan pengguna. Yang paling penting, itu terlihat pada daftar, di mana puluhan komponen diambil sekaligus. Kami belum mengoptimalkan semuanya, tetapi layar utama aplikasi tidak lagi melambat.

Poin utama dari artikel ini tercantum secara singkat di bawah ini.

  1. React Native : Props/State- .
  2. , React.PureComponent, , .
  3. , shouldComponentUpdate React.Memo .
  4. - . , (shallow compare). , .
  5. Mendukung perpustakaan tingkat presentasi dapat menyebabkan pemborosan sumber daya yang tidak terduga. Perlu hati-hati dalam aplikasi mereka.

Itu saja. Saya harap Anda menemukan informasi yang bermanfaat. Saya akan dengan senang hati menerima umpan balik!

Sumber yang bermanfaat


  1. Memahami Rendering dalam React + Redux
  2. Membandingkan Objek dalam JavaScript
  3. Meningkatkan Kinerja dalam Komponen Fungsional React menggunakan React.memo ()
  4. Bagaimana Discord mencapai kinerja iOS asli dengan React Native

All Articles