Leonard Monosa
Leonard M

Software Engineer at Stockbit & Bibit.id

React-18 useEffect double call, scary 😱 or awesome?

Seperti yang sudah kita ketahui pada update versi 18, react menuliskan pada dokumentasinya bahwa useEffect hooks akan dipanggil 2 kali pada strict mode, dan yang sebenarnya dilakukan oleh react adalah pada saat komponen di-mount, komponen tersebut akan di un-mount untuk di re-mount kembali, sounds weird? πŸ€” mari kita bahas!

App.js
useEffect(() => {
 console.info('called twice');
} ,[])

Mengapa hanya di strict mode? React ingin para developer live with it first before going production, tidak menutup kemungkinan bahwa pada versi react selanjutnya update ini akan dibawa ke production

Lalu bagaimana dengan API call? pasti kalau kita lihat didalam network maka akan ada 2 kali pemanggilan API, bagaimana solusinya? call inside handler!, namun mungkin ada kondisi dimana diharuskan untuk memanggil API melalui useEffect. maka kita harus cancel request tersebut ketika komponen tersebut di un-mount

App.js
useEffect(() => {
 //create controller to cancel the request
 const controller = axios.CancelToken.source();
 axios.get('person', { cancelToken: controller.token })
 .then((response) => setPerson(response.data));

 //cancel the call
 return () => controller.cancel();
}, []);

Namun bagaimana jika kalian memiliki lebih dari satu request? hmmmm… jika menggunakan approach diatas maka akan membuat code lebih kompleks dan tentu berantakan, tapi tenang aja berikut alternatif yang bisa kalian lakukan apabila memiliki lebih dari satu request! Yuk disimak!

1. Menghapus strict mode

penyebab terjadinya double mounting adalah strict mode, jadi cara yang paling mudah ialah dengan menghilangkan strict mode pada komponen index.js. dengan begitu useEffect akan berjalan normal layaknya yang ada pada React versi 17.

index.js
root.render(
 <React.StrictMode>
  <App />
 </React.StrictMode>
);

lalu ubah menjadi seperti berikut

index.js
root.render(<App />);

Namun, hey. cara ini bukan yang direkomendasikan! karna strict mode juga membantu kita code checking pada saat development mode sehingga jika ada kesalahan tidak akan menyakiti production!, lalu bagaimana solusinya selain menghilangkan strict mode? πŸ‘‡ πŸ‘‡

2. Membuat sebuah Custom Fetcher

Kita tahu bahwa javascript memiliki sebuah promise yang dapat digunakan sebagai cache. ketika promise di-resolve atau di-reject kita dapat menggunakan then atau catch untuk mendapatkan response dari promise tersebut. oleh karena itu kita dapat membuat fungsi untuk melakukan cache pada request sebagai berikut.

App.js
const cacheRequest = () => {
 // Create a cache of fetches by URL
 const fetchMap = {};
 return (url, options) => {
 // Check to see if its not in the cache otherwise fetch it
 if (!fetchMap[url]) {
 fetchMap[url] = axios.get(url).then((res) => res.data);
 }
 // Return the cached promise
 return fetchMap[url];
 };
};

Pada snippet diatas kita menyimpan sebuah key yaitu URL dari request yang kita lakukan, dan menyimpannya didalam sebuah map. apabila request sudah pernah dilakukan maka fungsi akan mengembalikan response yang telah kita cache, namun jika belum maka fungsi akan melakukan request ke server dan menyimpannya didalam cache.

3. Menggunakan React-Query

react-query merupakan library yang sangat amazing dan powerful, dengan react-query kita tidak perlu khawatir dengan double fetch!, karna react query akan menghandle seluruh request yang kita lakukan bahkan CACHE!. react query dapat digunakan dengan mudah menggunakan NPM package.

Yang perlu dilakukan pertama adalah membungkus aplikasi kita dengan QueryProvider komponen.

App.js
import { QueryClient, QueryClientProvider} from 'react-query';
 ...
 const AppWithProvider = () => (
 <QueryClientProvider client={new QueryClient()}>
  <App />
 </QueryClientProvider>
);

lalu didalam komponen gunakan useQuery hooks seperti berikut

App.js
const { data: people } = useQuery('people', () =>
 fetch('/people').then((res) => res.json())
);

Terlihat lebih mudah bukan 😎. dan tentu saja ini tidak double fetch!, ini hanya sebagian kecil dari react-query. kalian dapat explore lebih jauh lagi apa saja yang dapat dilakukan dengan react-query!. kalian juga dapat melakukan monitoring semua promise yang kita lakukan. dan juga tentu saja SSR!

4. Menggunakan State Manager

gue ga akan bahas secara detail codenya karna itu bergantung dengan state manager yang kalian gunakan, jika kalian menggunakan Redux Toolkit maka kalian dapat menggunakan RTK Query. Redux Toolkit tidak akan berpengaruh pada double mounting behavior ini.

Apa yang harus kalian hindari!

Jangan pernah menggunakan useRef sebagai jalan keluar. gue tau apa yang kalian pikirkan πŸ˜›. tidak ada jaminan bahwa komponen yang pertama di render di useEffect merupakan komponen yang sama juga ketika di render kembali. dan tentu juga ini bukan yang React ingin kalian lakukan.

Apa yang harus kalian lakukan?

cobalah beradaptasi dengan update yang ada pada React-18, jangan menghapus strict-mode kecuali kalian tau apa yang kalian lakukan. karna React ingin kalian Live with it! dengan begitu React dapat melakukan update lain yang lebih powerful.

sebagai contoh misalnya kita dapat mengembalikan atau merender komponen yang telah di un-mount atau kita kembali ke halaman sebelumnya dan react dapat dengan otomatis merender kembali komponen tersebut because it’s already there! and its blazzingly fast ⚑. menarik bukan?

sebagai penutup sampai sini dulu penjelasan dari gue, kalo kalian punya kritik atau saran jangan sungkan untuk say it, sampai jumpa lagi di artikel selanjutnya πŸ‘‹ πŸ’–