Memoization adalah teknik optimasi, mirip dengan caching. Ini bekerja dengan menyimpan hasil panggilan fungsi sebelumnya dan menggunakan hasil tersebut saat fungsi berjalan berikutnya. Ini sangat berguna dalam aplikasi komputasi berat yang mengulang panggilan fungsi pada parameter yang sama.

Anda dapat menggunakan memoisasi dalam JavaScript biasa dan juga di React, dalam beberapa cara berbeda.

Memoisasi dalam JavaScript

Untuk memoize suatu fungsi dalam JavaScript, Anda perlu menyimpan hasil fungsi tersebut dalam cache. Cache dapat berupa objek dengan argumen sebagai kunci dan hasil sebagai nilai.

Saat Anda memanggil fungsi ini, pertama-tama ia akan memeriksa apakah hasilnya ada di cache sebelum dijalankan. Jika ya, ia mengembalikan hasil yang di-cache. Jika tidak, itu akan dieksekusi.

Pertimbangkan fungsi ini:

fungsikotak(nomor) {
kembali angka * angka
}

Fungsi menerima argumen dan mengembalikan kuadratnya.

Untuk menjalankan fungsi tersebut, panggil dengan nomor seperti ini:

kotak(5) // 25

Dengan 5 sebagai argumen, square() akan berjalan cukup cepat. Namun, jika Anda menghitung kuadrat dari 70.000, akan ada penundaan yang nyata. Tidak banyak tapi penundaan tetap. Sekarang, jika Anda memanggil fungsi beberapa kali dan melewati 70.000, Anda akan mengalami penundaan di setiap panggilan.

Anda dapat menghilangkan penundaan ini menggunakan memoisasi.

konstan memoizedSquare = () => {
membiarkan cache = {};
kembali (angka) => {
jika (jumlah dalam cache) {
konsol.log('Menggunakan kembali nilai yang di-cache');
kembali cache[nomor];
} kalau tidak {
konsol.log('Menghitung hasil');
membiarkan hasil = angka * angka;

// cache itu baruhasilnilaiuntukBerikutnyawaktu
cache[nomor] = hasil;
kembali hasil;
}
}
}

Dalam contoh ini, fungsi memeriksa apakah hasil telah dihitung sebelumnya, dengan memeriksa apakah ada di objek cache. Jika memilikinya mengembalikan nilai yang sudah dihitung.

Ketika fungsi menerima nomor baru, ia menghitung nilai baru dan menyimpan hasilnya dalam cache sebelum kembali.

Sekali lagi contoh ini cukup sederhana, tetapi menjelaskan bagaimana memoisasi akan bekerja untuk meningkatkan kinerja suatu program.

Anda hanya boleh memoize fungsi murni. Fungsi-fungsi ini mengembalikan hasil yang sama ketika Anda memasukkan argumen yang sama. Jika Anda menggunakan memoisasi pada fungsi yang tidak murni, Anda tidak akan meningkatkan kinerja tetapi meningkatkan overhead Anda. Itu karena Anda memilih kecepatan daripada memori setiap kali Anda memoize suatu fungsi.

Memoisasi di React

Jika Anda ingin mengoptimalkan komponen React, React menyediakan memoisasi melalui hook useMemo(), React.memo, dan useCallBack().

Menggunakan useMemo()

useMemo() adalah Kait reaksi yang menerima fungsi dan larik dependensi.

konstan memoizedValue = useMemo(() => computeExpensiveValue (a, b), [a, b]);

Itu memoizes nilai yang dikembalikan dari fungsi itu. Nilai dalam larik dependensi menentukan kapan fungsi dijalankan. Hanya ketika mereka berubah, fungsi tersebut dieksekusi lagi.

Misalnya, komponen Aplikasi berikut memiliki nilai memo yang disebut hasil.

impor { gunakanMemo } dari "reaksi"
fungsiAplikasi(nilai) {
konstan kuadrat = (nilai) => {
kembali nilai * nilai
}
konstan hasil = gunakanMemo(
() => persegi (nilai),
[ nilai ]
);
kembali (
<div>{hasil (5)}</div>
)
}

Komponen Aplikasi memanggil square() pada setiap render. Performa akan menurun jika komponen Aplikasi dirender berkali-kali karena Alat peraga reaksi mengubah atau memperbarui status, terutama jika fungsi square() mahal.

Namun, karena useMemo() men-cache nilai yang dikembalikan, fungsi kuadrat tidak dijalankan di setiap render ulang kecuali argumen dalam larik dependensi berubah.

Menggunakan React.memo()

React.memo() adalah komponen tingkat tinggi yang menerima komponen React dan fungsi sebagai argumen. Fungsi menentukan kapan komponen harus diperbarui.

Fungsi ini opsional dan jika tidak disediakan, React.memo membuat perbandingan salinan sederhana dari properti komponen saat ini dengan properti sebelumnya. Jika alat peraga berbeda, itu memicu pembaruan. Jika propsnya sama, ia akan melewatkan rendering ulang dan menggunakan kembali nilai memo.

Fungsi opsional menerima props sebelumnya dan props berikutnya sebagai argumen. Anda kemudian dapat secara eksplisit membandingkan alat peraga ini untuk memutuskan apakah akan memperbarui komponen atau tidak.

Reaksi.memo(Komponen, [areEqual (prevProps, nextProps)])

Mari kita lihat contoh tanpa argumen fungsi opsional terlebih dahulu. Di bawah ini adalah komponen yang disebut Komentar yang menerima props nama dan email.

fungsiKomentar ({nama, komentar, suka}) {
kembali (
<div>
<p>{nama}</p>
<p>{komentar}</p>
<p>{suka}</p>
</div>
)
}

Komponen komentar memo akan membuat React.memo membungkusnya seperti ini:

konstan MemoizedComment = React.memo (Komentar)

Anda dapat memanggil lalu memanggilnya seperti komponen React lainnya.

<Nama Komentar Memo="Maria" komentar="Memoisasinya bagus" suka=1/>

Jika Anda ingin melakukan perbandingan props sendiri, berikan fungsi berikut ke React.memo sebagai argumen kedua.

impor Reaksi dari "reaksi"
fungsicekKomentarProps(prevProps, Props berikutnya) {
kembali prevProps.name nextProps.name
&& prevProps.comment NextProps.comment
&& prevProps.likes nextProps.likes
}

konstan MemoizedComment = React.memo (Komentar, checkCommentProps)

Jika checkProfileProps mengembalikan nilai true, komponen tidak diperbarui. Jika tidak, itu dirender ulang.

Fungsi kustom berguna saat Anda ingin menyesuaikan render ulang. Misalnya, Anda dapat menggunakannya untuk memperbarui komponen Komentar hanya ketika jumlah suka berubah.

Tidak seperti hook useMemo() yang hanya mencatat nilai yang dikembalikan dari suatu fungsi, React.memo memoize seluruh fungsi.

Gunakan React.memo hanya untuk komponen murni. Juga, untuk mengurangi biaya perbandingan, hanya memoize komponen yang alat peraganya sering berubah.

Menggunakan useCallBack()

Anda dapat menggunakan kait useCallBack() untuk memoize komponen fungsi.

konstan memoizedCallback = gunakanCallback(
() => {
melakukan Sesuatu (a, b);
},
[a, b],
);

Fungsi akan diperbarui hanya ketika nilai dalam larik dependensi berubah. Hook berfungsi seperti callback useMemo(), tetapi memoize komponen fungsi di antara render alih-alih memoizing nilai.

Pertimbangkan contoh berikut dari fungsi memo yang memanggil API.

impor { useCallback, useEffect } dari "reaksi";
konstan Komponen = () => {
konstan getData = useCallback(() => {
konsol.log('panggil API');
}, []);
gunakanEfek(() => {
getData();
}, [getData]);
};

Fungsi getData() yang dipanggil di useEffect akan dipanggil lagi hanya ketika nilai getData berubah.

Haruskah Anda Menghafal?

Dalam tutorial ini, Anda mempelajari apa itu memoisasi, manfaatnya, dan bagaimana menerapkannya dalam JavaScript dan React. Namun, Anda harus tahu bahwa React sudah cepat. Dalam kebanyakan kasus, memoisasi komponen atau nilai menambah biaya perbandingan dan tidak meningkatkan kinerja. Karena itu, hanya memoize komponen yang mahal.

React 18 juga memperkenalkan kait baru seperti useId, useTransition, dan useInsertionEffect. Anda dapat menggunakan ini untuk meningkatkan kinerja dan pengalaman pengguna aplikasi React.