why-did-you-render
oleh Welldone Software patch monyet React
untuk memberi tahu Anda tentang kemungkinan perenderan ulang yang dapat dihindari. (Bekerja dengan React Native
juga.)
Misalnya, jika Anda meneruskan style={{width: '100%'}}
ke komponen murni yang besar, komponen tersebut akan selalu dirender ulang pada setiap pembuatan elemen:
<BigListPureComponent style={{lebar: '100%'}}/>
Ini juga dapat membantu Anda melacak kapan dan mengapa komponen tertentu dirender ulang.
Versi terbaru perpustakaan telah diuji (pengujian unit dan E2E) hanya dengan React@18
. Untuk React 17 dan 16 silahkan gunakan versi @^7.
npm install @welldone-software/why-did-you-render --save-dev
atau
yarn add --dev @welldone-software/why-did-you-render
Jika Anda menggunakan transformasi JSX automatic
, atur perpustakaan menjadi sumber impor, dan pastikan preset-react
berada dalam mode development
.
['@babel/preset-react', { waktu proses: 'otomatis', pengembangan: process.env.NODE_ENV === 'pengembangan', importSource: '@welldone-software/why-did-you-render',}]
Sayangnya, metro-react-native-babel-preset
yang disertakan dengan react-native tidak memungkinkan Anda mengubah opsi plugin babel/plugin-transform-react-jsx
. Cukup tambahkan plugin dengan opsi seperti yang tercantum di bawah ini dan mulai react-native packager seperti biasa. Env default untuk babel adalah "pengembangan". Jika Anda tidak menggunakan expo saat bekerja dengan react-native, metode berikut akan membantu Anda.
module.exports = { preset: ['modul:metro-react-native-babel-preset'], env: { pengembangan: { plugin: [['@babel/plugin-transform-react-jsx', { waktu proses: ' klasik' }]], }, },}
Anda dapat meneruskan params ke @babel/preset-react
melalui babel-preset-expo
// babel.config.jsmodule.exports = fungsi (api) { api.cache(benar); return { preset: [ [ "babel-preset-expo", { jsxImportSource: "@welldone-software/why-did-you-render", }, ], ], };};
Pemberitahuan: Create React App (CRA) ^4 menggunakan transformasi JSX
automatic
. Lihat komentar berikut tentang cara melakukan langkah ini dengan CRA
Buat file wdyr.js
dan impor sebagai impor pertama di aplikasi Anda.
wdyr.js
:
import React from 'react';if (process.env.NODE_ENV === 'development') { const WhyDidYouRender = require('@welldone-software/why-did-you-render'); kenapaDidYouRender(Bereaksi, { trackAllPureComponents: true, });}
Pemberitahuan: Perpustakaan JANGAN PERNAH digunakan dalam produksi karena memperlambat React
Di TypeScript, panggil file wdyr.ts dan tambahkan baris berikut ke bagian atas file untuk mengimpor tipe paket:
/// <jenis referensi="@welldone-software/mengapa-Anda-render" />
Impor wdyr
sebagai impor pertama (bahkan sebelum react-hot-loader
):
index.js
:
impor './wdyr'; // <--- impor pertama 'react-hot-loader';impor {hot} dari 'react-hot-loader/root';impor React dari 'react';impor ReactDOM dari 'react-dom';// . ..import {App} dari './app';// ...const HotApp = hot(App);// ...ReactDOM.render(<HotApp/>, dokumen.getElementById('root'));
Jika Anda menggunakan trackAllPureComponents
seperti yang kami sarankan, semua komponen murni (React.PureComponent atau React.memo) akan dilacak.
Jika tidak, tambahkan whyDidYouRender = true
ke kelas/fungsi komponen yang ingin Anda lacak. (fe Component.whyDidYouRender = true
)
Informasi lebih lanjut tentang apa yang dilacak dapat ditemukan di Komponen Pelacakan.
Tidak dapat melihat log WDYR? Lihat bagian pemecahan masalah atau cari di bagian masalahnya.
Selain itu, pelacakan kait khusus dapat dilakukan dengan menggunakan trackExtraHooks
. Misalnya jika Anda ingin melacak useSelector
dari React Redux:
wdyr.js
:
import React from 'react';// Untuk react-native Anda mungkin ingin menggunakan // flag __DEV__ alih-alih process.env.NODE_ENV === 'development'if (process.env.NODE_ENV === 'development') { const WhyDidYouRender = memerlukan('@welldone-software/mengapa-Anda-render'); const ReactRedux = memerlukan('reaksi-redux'); kenapaDidYouRender(React, { trackAllPureComponents: true, trackExtraHooks: [ [ReactRedux, 'useSelector'] ] });}
Perhatikan bahwa saat ini ada masalah dengan penulisan ulang ekspor file yang diimpor di
webpack
. Solusi cepat dapat membantu: #85 - trackExtraHooks tidak dapat menyetel properti.
Mengapa Anda Merender Komponen React Murni Mr. Big???
Skenario perbaikan umum yang dapat dibantu oleh perpustakaan ini
React Hooks - Memahami dan memperbaiki masalah hooks
Mengapa Anda Render v4 Dirilis! - Dukungan TypeScript, Pelacakan kait khusus (seperti useSelector React-Redux), Pelacakan semua komponen murni.
Contoh Next.js
React-Redux Dengan Kait
Mobx saat ini tidak didukung
Plugin sirip React-Native dibuat oleh @allen-hsu
Anda dapat menguji perpustakaan di kotak pasir resmi.
Dan kotak pasir resmi lainnya dengan pelacakan kait
Anda dapat melacak semua komponen murni (React.PureComponent atau React.memo) menggunakan opsi trackAllPureComponents: true
.
Anda juga dapat melacak secara manual komponen apa pun yang Anda inginkan dengan menyetel whyDidYouRender
pada komponen tersebut seperti ini:
class BigList extends React.Component { static WhyDidYouRender = true render(){ return ( //beberapa render berat yang ingin Anda pastikan tidak terjadi jika tidak diperlukan ) }}
Atau untuk komponen fungsional:
const BigListPureComponent = props => ( <div> //beberapa komponen berat yang ingin Anda pastikan tidak terjadi jika tidak diperlukan </div>)BigListPureComponent.whyDidYouRender = true
Anda juga dapat meneruskan objek untuk menentukan pengaturan pelacakan lebih lanjut:
EnhancedMenu.whyDidYouRender = { logOnDifferentValues: true, customName: 'Menu'}
logOnDifferentValues
:
Biasanya, hanya rendering ulang yang disebabkan oleh nilai yang sama dalam notifikasi pemicu props/status:
render(<Menu a={1}/>)render(<Menu a={1}/>)
Opsi ini akan memicu notifikasi meskipun terjadi karena props/status yang berbeda (Jadi, karena rendering ulang yang "sah"):
render(<Menu a={1}/>)render(<Menu a={2}/>)
customName
:
Terkadang nama komponen bisa hilang atau sangat merepotkan. Misalnya:
withPropsOnChange(withPropsOnChange(withStateHandlers(withPropsOnChange(withState(withPropsOnChange(siklus hidup(withPropsOnChange(withPropsOnChange(onlyUpdateForKeys(LoadNamesp ace(Hubungkan(withState(withState(withPropsOnChange(siklus hidup(denganPropsOnChange(withHandlers(withHandlers(withHandlers(withHandlers(Connect(siklus hidup(Menu))))))))))))))))))))))))
Secara opsional, Anda dapat meneruskan options
sebagai parameter kedua. Opsi berikut tersedia:
include: [RegExp, ...]
( null
secara default)
exclude: [RegExp, ...]
( null
secara default)
trackAllPureComponents: false
trackHooks: true
trackExtraHooks: []
logOwnerReasons: true
logOnDifferentValues: false
hotReloadBufferMs: 500
onlyLogs: false
collapseGroups: false
titleColor
diffNameColor
diffPathColor
notifier: ({Component, displayName, hookName, prevProps, prevState, prevHook, nextProps, nextState, nextHook, reason, options, ownerDataMap}) => void
getAdditionalOwnerData: (element) => {...}
null
) Anda dapat menyertakan atau mengecualikan pelacakan komponen berdasarkan nama tampilannya menggunakan opsi include
dan exclude
.
Misalnya, kode berikut digunakan untuk melacak semua perenderan ulang berlebihan yang disebabkan oleh React-Redux lama:
kenapaDidYouRender(Reaksi, { sertakan: [/^ConnectFunction/] });
Pemberitahuan: pengecualian lebih diprioritaskan daripada
include
dan penyetelanwhyDidYouRender =
secara manual
false
) Anda dapat melacak semua komponen murni (baik komponen React.memo
maupun React.PureComponent
)
Pemberitahuan: Anda dapat mengecualikan pelacakan komponen tertentu dengan
whyDidYouRender = false
true
)Anda dapat menonaktifkan pelacakan perubahan kait.
Memahami dan memperbaiki masalah kait.
[]
)Lacak kait khusus:
kenapaDidYouRender(React, { trackExtraHooks: [ // perhatikan bahwa 'useSelector' adalah ekspor bernama [ReactRedux, 'useSelector'], ]});
Saat ini terdapat masalah dengan penulisan ulang ekspor file yang diimpor di webpack. Solusi tersedia di sini: #85 - trackExtraHooks tidak dapat menyetel properti
true
)Salah satu cara untuk memperbaiki masalah rendering ulang adalah dengan mencegah pemilik komponen melakukan rendering ulang.
Opsi ini true
secara default dan memungkinkan Anda melihat alasan mengapa komponen pemilik dirender ulang.
false
)Biasanya, Anda hanya menginginkan log tentang perenderan ulang komponen jika hal tersebut sebenarnya dapat dihindari.
Dengan opsi ini, dimungkinkan untuk melacak semua perenderan ulang.
Misalnya:
render(<BigListPureComponent a={1}/>)render(<BigListPureComponent a={2}/>)// hanya akan mencatat log jika Anda menggunakan {logOnDifferentValues: true}
500
)Waktu dalam milidetik untuk mengabaikan pembaruan setelah hot reload terdeteksi.
Ketika hot reload terdeteksi, kami mengabaikan semua pembaruan untuk hotReloadBufferMs
agar tidak mengirim spam ke konsol.
false
) Jika Anda tidak ingin menggunakan console.group
untuk mengelompokkan log, Anda dapat mencetaknya sebagai log sederhana.
false
)Log yang dikelompokkan dapat diciutkan.
'#058'
)'blue'
)'red'
)Mengontrol warna yang digunakan dalam notifikasi konsol
Anda dapat membuat notifikasi khusus jika notifikasi default tidak sesuai dengan kebutuhan Anda.
undefined
)Anda dapat menyediakan fungsi yang mengambil data tambahan dari elemen reaksi asli. Objek yang dikembalikan dari fungsi ini akan ditambahkan ke ownerDataMap yang nantinya dapat diakses dalam penggantian fungsi pemberi tahu Anda.
Jika Anda sedang dalam produksi, WDYR mungkin dinonaktifkan.
Mungkin tidak ada komponen yang dilacak
Periksa Komponen Pelacakan sekali lagi.
Jika Anda hanya melacak komponen murni menggunakan trackAllPureComponents: true
maka Anda hanya akan melacak salah satunya (React.PureComponent atau React.memo), mungkin tidak ada komponen Anda yang murni sehingga tidak ada satupun yang akan terlacak.
Mungkin Anda tidak memiliki masalah
Coba buat masalah dengan merender sementara seluruh aplikasi dua kali di titik masuknya:
index.js
:
const HotApp = hot(App);HotApp.whyDidYouRender = true;ReactDOM.render(<HotApp/>, document.getElementById('root'));ReactDOM.render(<HotApp/>, document.getElementById('root') );
Saat ini ada masalah dengan penulisan ulang ekspor file yang diimpor di webpack
. Solusi cepat dapat membantu: #85 - trackExtraHooks tidak dapat menyetel properti.
connect
HOC mengirim spam ke konsol Karena connect
hoist bersifat statis, jika Anda menambahkan WDYR ke komponen dalam, WDYR juga akan ditambahkan ke komponen HOC tempat hook kompleks dijalankan.
Untuk memperbaikinya, tambahkan whyDidYouRender = true
static ke komponen setelah koneksi:
const SimpleComponent = ({a}) => <div data-testid="foo">{ab}</div>) // tidak sebelum koneksi: // SimpleComponent.whyDidYouRender = true const ConnectedSimpleComponent = connect( state => ({a: state.a}) )(SimpleComponent) // setelah koneksi: SimpleComponent.whyDidYouRender = true
Untuk melihat peta sumber perpustakaan, gunakan pemuat peta sumber.
Terinspirasi dari karya sebelumnya berikut ini:
github.com/maicki/why-did-you-update (tidak lagi bersifat publik) yang sempat saya simpan selama beberapa waktu.
https://github.com/garbles/why-did-you-update di mana penyelaman mendalam ke dalam debugging kinerja React dikreditkan atas ide tersebut.
Perpustakaan ini berlisensi MIT.