Bereaksi render elemen yang tidak perlu
Saya baru saja mulai mempelajari React dan sedang membuat aplikasi kecil yang membuat panggilan ke API kutipan. API memiliki titik akhir yang mengembalikan kutipan acak. Saat aplikasi pertama kali dimuat, aplikasi melakukan panggilan ke API dan menampilkan kutipan, dan ada tombol yang bisa diklik untuk mendapatkan kutipan acak baru (panggilan baru ke API).
Saya memiliki komponen root bernama App. Komponen ini memiliki komponen QuoteWrap sebagai anak. Komponen QuoteWrap memiliki dua anak: tombol yang digunakan untuk mendapatkan kutipan acak baru dan komponen Kutipan yang menunjukkan penulis kutipan dan kutipan itu sendiri. Ini adalah kode di dalam komponen QuoteWrap:
export default function QuoteWrap() {
const { quoteData, isLoading, fireNewCall } = useQuote();
const handleClick = () => {
fireNewCall();
};
return(
<>
<button onClick={handleClick}>Get random quote</button>
{ isLoading ?
<h2>Loading...</h2>
:
<Quote author={quoteData.author} quote={quoteData.quote} />
}
</>
);
}
useQuote () adalah hook khusus yang mengelola panggilan ke API dan mengembalikan 3 nilai: 1- data, 2- jika panggilan sedang dalam proses dan 3- fungsi untuk melakukan panggilan ke API.
Jelas, setiap kali tombol diklik, seluruh komponen QuoteWrap dirender ulang (seperti perubahan quoteData dan isLoading). Tapi sungguh, tombol tidak perlu dirender ulang karena tidak pernah berubah.
Jadi saya berpikir: oke, saya bisa memindahkan tombol ke komponen App. Tapi kemudian saya tidak memiliki akses ke fungsi fireNewCall di hook useQuote.
Bagaimana cara mencegah tombol dirender ulang? Apakah ini penting dalam kasus ini atau apakah saya terlalu terobsesi dengan pembuatan ulang React?
Terima kasih!
Jawaban
Komponen Anda akan dirender ulang setiap kali fungsi handleClick berubah, yaitu setiap kali QuoteWrap dirender.
Solusinya adalah hook useCallback. useCallback akan mengembalikan fungsi yang sama ke handleClick, setiap kali QuoteWrap dirender, selama dependensi tidak berubah.
https://reactjs.org/docs/hooks-reference.html#usecallback
Anda akan menggunakannya seperti ini:
const handleClick = useCallback(() => {
fireNewCall();
},[fireNewCall]);
fireNewCall adalah dependensi, jadi selama useQuote mengembalikan fungsi fireNewCall yang stabil, tombol Anda tidak akan dirender ulang, karena properti handleClick belum berubah.
Saya pikir Anda mungkin terlalu terobsesi dengan pembuatan ulang React. Tombol harus dirender ulang karena, handleClickharus diubah ketika fireNewCalldiubah untuk beberapa kasus. Kalaupun, handleClicktidak akan pernah berubah. Tidak perlu memikirkan tentang render ulang elemen.
Hampir seperti yang dikatakan Benjamin dan Viet - dalam kode asli Anda, fungsi baru ditugaskan untuk menangani Klik pada setiap render. Anda bisa menggunakan React.useCallbackuntuk mempertahankan referensi fungsi asli dan hanya memperbaruinya ketika sesuatu dalam larik ketergantungan berubah - dalam hal ini, hanya fireNewCallperlu masuk ke larik ketergantungan.
Tapi seperti yang dikatakan Viet, jangan terlalu terobsesi dengannya. Penggunaan React.useCallbackbahkan mungkin memperlambat kode Anda. Lihat Kent C. Dodds Kapan useMemo dan posting useCallback untuk wawasan lebih lanjut.