✨ 17 React Hooks Yang Mendukung 90% Komponen Modern (Panduan Lengkap 2024)
React Hooks telah merevolusi cara kita membangun komponen di React. Mereka memungkinkan kita menggunakan state dan fitur React lainnya dalam komponen fungsi, yang dulunya hanya mungkin dilakukan di komponen kelas. Dengan begitu banyak hooks yang tersedia, penting untuk fokus pada yang paling penting dan efektif. Artikel ini akan membahas 17 React Hooks yang mendukung 90% komponen modern, dilengkapi dengan contoh kode, penjelasan mendalam, dan praktik terbaik SEO.
Daftar Isi
- Pendahuluan: Mengapa React Hooks Penting?
- 1.
useState
: Manajemen State Dasar - 2.
useEffect
: Mengelola Efek Samping - 3.
useContext
: Berbagi State Antar Komponen - 4.
useRef
: Mengakses Elemen DOM dan Menyimpan Nilai - 5.
useCallback
: Memoizing Fungsi - 6.
useMemo
: Memoizing Nilai - 7.
useReducer
: Manajemen State yang Lebih Kompleks - 8.
useImperativeHandle
: Mengakses Instans Komponen Anak - 9.
useLayoutEffect
: Efek Samping Sinkronous - 10.
useDebugValue
: Menambahkan Informasi Debug ke React DevTools - 11.
useTransition
: Mengelola Transisi State - 12.
useDeferredValue
: Menunda Pembaruan Kurang Penting - 13.
useId
: Membuat ID Unik - 14.
useSyncExternalStore
: Berlangganan ke Penyimpanan Eksternal - 15.
useInsertionEffect
: Memanipulasi DOM sebelum Layout - 16.
useOptimisticUpdate
: Pembaruan Optimis UI - 17. Custom Hooks: Membuat Logika yang Dapat Digunakan Kembali
- Kesimpulan: Menguasai React Hooks untuk Pengembangan Modern
Pendahuluan: Mengapa React Hooks Penting?
Sebelum React Hooks diperkenalkan, komponen stateful hanya bisa dibuat menggunakan komponen kelas. Hal ini seringkali membuat kode menjadi lebih kompleks dan sulit dibaca. Hooks memungkinkan kita menggunakan state dan fitur React lainnya dalam komponen fungsi, sehingga kode menjadi lebih sederhana, bersih, dan mudah dikelola. Mereka juga mendorong penggunaan kembali logika stateful antar komponen, yang mengarah pada kode yang lebih modular dan efisien.
Hooks juga mempermudah pengujian komponen React. Dengan memisahkan logika stateful dari komponen UI, kita dapat menguji logika tersebut secara terpisah, memastikan bahwa aplikasi kita berfungsi seperti yang diharapkan.
1. useState
: Manajemen State Dasar
useState
adalah hook paling dasar dan paling sering digunakan di React. Ini memungkinkan kita menambahkan state ke komponen fungsi. Hook ini mengembalikan sepasang nilai: nilai state saat ini dan fungsi untuk memperbarui nilai tersebut.
Sintaks:
const [state, setState] = useState(initialValue);
Contoh:
import React, { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0);
return (
Count: {count}
);
}
export default Counter;
Dalam contoh ini, count
adalah state yang menyimpan nilai hitungan, dan setCount
adalah fungsi yang digunakan untuk memperbarui nilai count
. Nilai awal count
adalah 0.
Tips dan Trik:
- Gunakan
useState
untuk menyimpan data sederhana seperti string, angka, dan boolean. - Anda dapat menggunakan banyak
useState
hooks dalam satu komponen untuk mengelola state yang berbeda. - Gunakan fungsi pembaruan state untuk memperbarui state berdasarkan nilai sebelumnya, terutama saat bekerja dengan pembaruan asinkron. Contoh:
setCount(prevCount => prevCount + 1)
.
2. useEffect
: Mengelola Efek Samping
useEffect
memungkinkan kita melakukan efek samping dalam komponen fungsi. Efek samping adalah operasi yang berinteraksi dengan dunia luar, seperti mengambil data dari API, memperbarui DOM secara langsung, atau mengatur timer.
Sintaks:
useEffect(() => {
// Efek samping
return () => {
// Fungsi pembersihan (opsional)
};
}, [dependencies]);
Contoh:
import React, { useState, useEffect } from 'react';
function DataFetcher() {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
async function fetchData() {
try {
const response = await fetch('https://jsonplaceholder.typicode.com/todos/1');
const jsonData = await response.json();
setData(jsonData);
} catch (error) {
console.error('Error fetching data:', error);
} finally {
setLoading(false);
}
}
fetchData();
return () => {
// Fungsi pembersihan (misalnya, membatalkan permintaan fetch)
};
}, []); // Array dependencies kosong berarti efek dijalankan hanya sekali saat komponen dipasang
if (loading) {
return Loading...
;
}
if (!data) {
return Error fetching data.
;
}
return (
Title: {data.title}
Completed: {data.completed ? 'Yes' : 'No'}
);
}
export default DataFetcher;
Dalam contoh ini, useEffect
digunakan untuk mengambil data dari API saat komponen dipasang. Array dependencies kosong ([]
) memastikan bahwa efek hanya dijalankan sekali. Fungsi pembersihan (return () => {}
) bersifat opsional dan digunakan untuk membatalkan efek atau membersihkan sumber daya saat komponen dilepas.
Tips dan Trik:
- Gunakan array dependencies untuk mengontrol kapan efek dijalankan.
- Sertakan semua variabel yang digunakan di dalam efek dalam array dependencies.
- Gunakan fungsi pembersihan untuk mencegah kebocoran memori.
- Hindari melakukan efek samping secara langsung di dalam komponen, gunakan
useEffect
sebagai gantinya.
3. useContext
: Berbagi State Antar Komponen
useContext
memungkinkan kita mengakses nilai context dalam komponen fungsi. Context menyediakan cara untuk meneruskan data melalui pohon komponen tanpa harus secara manual meneruskannya melalui setiap level.
Sintaks:
const value = useContext(MyContext);
Contoh:
import React, { createContext, useContext, useState } from 'react';
const ThemeContext = createContext();
function ThemeProvider({ children }) {
const [theme, setTheme] = useState('light');
const toggleTheme = () => {
setTheme(prevTheme => (prevTheme === 'light' ? 'dark' : 'light'));
};
return (
{children}
);
}
function ThemedComponent() {
const { theme, toggleTheme } = useContext(ThemeContext);
return (
Current Theme: {theme}
);
}
function App() {
return (
);
}
export default App;
Dalam contoh ini, ThemeContext
dibuat untuk menyediakan tema dan fungsi untuk mengubah tema. ThemeProvider
menyediakan nilai context, dan ThemedComponent
menggunakan useContext
untuk mengakses nilai context dan memperbarui UI berdasarkan tema saat ini.
Tips dan Trik:
- Gunakan
useContext
untuk berbagi data global seperti tema, bahasa, atau informasi pengguna. - Pastikan context provider ditempatkan di atas komponen yang menggunakan context.
- Hindari menggunakan context untuk state yang sering berubah, karena ini dapat menyebabkan kinerja yang buruk.
4. useRef
: Mengakses Elemen DOM dan Menyimpan Nilai
useRef
memungkinkan kita mengakses elemen DOM secara langsung dan menyimpan nilai mutable yang tidak memicu pembaruan ulang saat diubah.
Sintaks:
const refContainer = useRef(initialValue);
Contoh:
import React, { useRef, useEffect } from 'react';
function FocusInput() {
const inputRef = useRef(null);
useEffect(() => {
// Fokuskan input saat komponen dipasang
inputRef.current.focus();
}, []);
return (
);
}
export default FocusInput;
Dalam contoh ini, useRef
digunakan untuk mengakses elemen input DOM. Efek useEffect
digunakan untuk memfokuskan input saat komponen dipasang.
Tips dan Trik:
- Gunakan
useRef
untuk mengakses elemen DOM secara langsung. - Gunakan
useRef
untuk menyimpan nilai mutable yang tidak memicu pembaruan ulang. - Berhati-hatilah saat memanipulasi DOM secara langsung, karena ini dapat menyebabkan masalah kinerja.
5. useCallback
: Memoizing Fungsi
useCallback
memungkinkan kita untuk memoizing fungsi. Ini berarti bahwa fungsi hanya akan dibuat ulang jika salah satu dependenciesnya berubah. Ini dapat meningkatkan kinerja dengan mencegah pembaruan ulang komponen yang tidak perlu.
Sintaks:
const memoizedCallback = useCallback(
() => {
// Fungsi yang akan di-memoize
},
[dependencies],
);
Contoh:
import React, { useState, useCallback } from 'react';
function Button({ onClick, children }) {
console.log('Button rendered'); // Untuk melihat apakah komponen di-render ulang
return ;
}
const MemoizedButton = React.memo(Button); // Mengoptimalkan re-render button
function ParentComponent() {
const [count, setCount] = useState(0);
// `increment` akan selalu menjadi fungsi yang sama selama `setCount` tidak berubah.
const increment = useCallback(() => {
setCount(c => c + 1);
}, []);
return (
Count: {count}
{/*Increment fungsi callback yang sama diteruskan, Button hanya re-render saat props nya berubah.*/}
Increment
);
}
export default ParentComponent;
Dalam contoh ini, useCallback
digunakan untuk memoizing fungsi increment
. Ini berarti bahwa fungsi increment
hanya akan dibuat ulang jika setCount
berubah. React.memo
digunakan untuk memoizing komponen Button
, sehingga komponen hanya akan di-render ulang jika propsnya berubah.
Tips dan Trik:
- Gunakan
useCallback
untuk memoizing fungsi yang diteruskan sebagai props ke komponen anak. - Sertakan semua variabel yang digunakan di dalam fungsi dalam array dependencies.
- Gunakan
React.memo
untuk memoizing komponen yang menerima fungsi yang di-memoize sebagai props.
6. useMemo
: Memoizing Nilai
useMemo
memungkinkan kita untuk memoizing nilai. Ini berarti bahwa nilai hanya akan dihitung ulang jika salah satu dependenciesnya berubah. Ini dapat meningkatkan kinerja dengan mencegah perhitungan ulang yang tidak perlu.
Sintaks:
const memoizedValue = useMemo(
() => {
// Fungsi yang menghasilkan nilai
return computeExpensiveValue(a, b);
},
[a, b],
);
Contoh:
import React, { useState, useMemo } from 'react';
function ExpensiveCalculation({ number }) {
// Fungsi hipotetis yang butuh banyak waktu untuk dihitung.
const fibonacci = (n) => {
if (n <= 1) {
return 1;
}
return fibonacci(n - 1) + fibonacci(n - 2);
};
// `useMemo` hanya akan menjalankan `fibonacci` ketika `number` berubah.
const result = useMemo(() => fibonacci(number), [number]);
return (
Fibonacci of {number} is {result}
);
}
function App() {
const [count, setCount] = useState(10);
return (
);
}
export default App;
Dalam contoh ini, useMemo
digunakan untuk memoizing hasil perhitungan Fibonacci. Ini berarti bahwa perhitungan Fibonacci hanya akan dilakukan ulang jika number
berubah. Ini dapat meningkatkan kinerja jika perhitungan Fibonacci membutuhkan waktu yang lama.
Tips dan Trik:
- Gunakan
useMemo
untuk memoizing nilai yang membutuhkan waktu lama untuk dihitung. - Sertakan semua variabel yang digunakan di dalam fungsi dalam array dependencies.
- Hindari menggunakan
useMemo
untuk nilai yang murah untuk dihitung, karena overhead memoizing mungkin lebih besar daripada keuntungan kinerja.
7. useReducer
: Manajemen State yang Lebih Kompleks
useReducer
adalah alternatif untuk useState
yang lebih cocok untuk mengelola state yang lebih kompleks. Ini memungkinkan kita untuk menentukan state berdasarkan tindakan, yang membuatnya lebih mudah untuk melacak dan mengelola perubahan state.
Sintaks:
const [state, dispatch] = useReducer(reducer, initialArg, init);
Contoh:
import React, { useReducer } from 'react';
// Mendefinisikan fungsi reducer yang mengelola perubahan state berdasarkan tindakan.
const counterReducer = (state, action) => {
switch (action.type) {
case 'INCREMENT':
return { count: state.count + 1 };
case 'DECREMENT':
return { count: state.count - 1 };
default:
return state;
}
};
function Counter() {
// Menggunakan `useReducer` untuk mengelola state, dengan `counterReducer` sebagai fungsi reducer.
const [state, dispatch] = useReducer(counterReducer, { count: 0 });
return (
Count: {state.count}
{/* Tombol yang memicu tindakan `INCREMENT` dengan memanggil `dispatch`. */}
{/* Tombol yang memicu tindakan `DECREMENT` dengan memanggil `dispatch`. */}
);
}
export default Counter;
Dalam contoh ini, useReducer
digunakan untuk mengelola state hitungan. Reducer counterReducer
menentukan bagaimana state harus diubah berdasarkan tindakan yang dikirimkan. Fungsi dispatch
digunakan untuk mengirimkan tindakan ke reducer.
Tips dan Trik:
- Gunakan
useReducer
untuk mengelola state yang kompleks dan memiliki banyak perubahan. - Definisikan reducer yang jelas dan ringkas.
- Gunakan konstanta untuk tindakan untuk menghindari kesalahan ketik.
8. useImperativeHandle
: Mengakses Instans Komponen Anak
useImperativeHandle
memungkinkan kita menyesuaikan instans yang diekspos ke komponen induk saat menggunakan ref
. Ini dapat berguna untuk membuat API yang lebih terkontrol untuk komponen kita.
Sintaks:
useImperativeHandle(ref, createHandle, [deps])
Contoh:
import React, { useRef, useImperativeHandle, forwardRef } from 'react';
const FancyInput = forwardRef((props, ref) => {
const inputRef = useRef();
useImperativeHandle(ref, () => ({
focus: () => {
inputRef.current.focus();
},
getValue: () => {
return inputRef.current.value;
},
}));
return ;
});
function ParentComponent() {
const inputRef = useRef();
const handleFocus = () => {
inputRef.current.focus();
};
const handleGetValue = () => {
alert(inputRef.current.getValue());
};
return (
);
}
export default ParentComponent;
Dalam contoh ini, useImperativeHandle
digunakan untuk menyesuaikan instans yang diekspos oleh komponen FancyInput
. Komponen induk dapat menggunakan ref
untuk mengakses fungsi focus
dan getValue
pada instans FancyInput
.
Tips dan Trik:
- Gunakan
useImperativeHandle
dengan bijak, karena ini dapat membuat kode menjadi lebih sulit untuk dipahami. - Hanya ekspos fungsi yang benar-benar diperlukan oleh komponen induk.
9. useLayoutEffect
: Efek Samping Sinkronous
useLayoutEffect
mirip dengan useEffect
, tetapi dijalankan secara sinkronous setelah semua perubahan DOM. Ini dapat berguna untuk melakukan pengukuran DOM atau membuat perubahan visual yang harus dilakukan sebelum browser melukis layar.
Sintaks:
useLayoutEffect(() => {
// Efek samping sinkronous
return () => {
// Fungsi pembersihan (opsional)
};
}, [dependencies]);
Contoh:
import React, { useState, useLayoutEffect, useRef } from 'react';
function MeasureExample() {
const [height, setHeight] = useState(0);
const divRef = useRef(null);
useLayoutEffect(() => {
if (divRef.current) {
// Mengukur tinggi div setelah layout selesai
setHeight(divRef.current.offsetHeight);
}
}, []); // Jalankan hanya sekali setelah mounting
return (
Kandungannya Disini.
Tinggi Div: {height}px
);
}
export default MeasureExample;
Dalam contoh ini, useLayoutEffect
digunakan untuk mengukur tinggi elemen div setelah layout selesai. Ini memastikan bahwa tinggi yang diukur adalah tinggi yang benar.
Tips dan Trik:
- Gunakan
useLayoutEffect
hanya jika Anda perlu melakukan pengukuran DOM atau membuat perubahan visual yang harus dilakukan sebelum browser melukis layar. - Berhati-hatilah saat menggunakan
useLayoutEffect
, karena ini dapat memblokir browser dari melukis layar dan menyebabkan masalah kinerja. - Jika memungkinkan, gunakan
useEffect
sebagai gantinya.
10. useDebugValue
: Menambahkan Informasi Debug ke React DevTools
useDebugValue
memungkinkan kita menambahkan informasi debug ke React DevTools. Ini dapat berguna untuk men-debug custom hooks kita.
Sintaks:
useDebugValue(value, format);
Contoh:
import { useState, useEffect, useDebugValue } from 'react';
function useFriendStatus(friendID) {
const [isOnline, setIsOnline] = useState(null);
useEffect(() => {
function handleStatusChange(status) {
setIsOnline(status.isOnline);
}
// Anggap ini adalah panggilan ke fungsi yang menghubungkan/melepaskan hook ke API eksternal
// dan memperbarui `isOnline` ketika status teman berubah
//API.subscribeToFriendStatus(friendID, handleStatusChange);
//return () => {
// API.unsubscribeFromFriendStatus(friendID, handleStatusChange);
//};
// kita mensimulasikan update status dengan timer
const timer = setInterval(() => {
setIsOnline(Math.random() < 0.5)
}, 2000);
return () => clearInterval(timer);
}, [friendID]);
// Menampilkan pesan yang lebih bermakna di DevTools
useDebugValue(isOnline ? 'Online' : 'Offline');
return isOnline;
}
function FriendListItem({ friend }) {
const isOnline = useFriendStatus(friend.id);
return (
{friend.name} - {isOnline === null ? 'Loading...' : isOnline ? 'Online' : 'Offline'}
);
}
function FriendList({ friends }) {
return (
{friends.map((friend) => (
))}
);
}
function App() {
const friends = [
{ id: 1, name: 'Phoebe' },
{ id: 2, name: 'Rachel' },
{ id: 3, name: 'Ross' },
];
return ;
}
export default App;
Dalam contoh ini, useDebugValue
digunakan untuk menampilkan pesan yang lebih bermakna di React DevTools saat men-debug hook useFriendStatus
.
Tips dan Trik:
- Gunakan
useDebugValue
untuk menambahkan informasi debug ke custom hooks Anda. - Gunakan fungsi
format
untuk memformat nilai sebelum ditampilkan di React DevTools.
11. useTransition
: Mengelola Transisi State
useTransition
memungkinkan Anda menjaga UI tetap responsif meskipun ada pembaruan yang tertunda. Ini berguna ketika pembaruan state mungkin membutuhkan waktu untuk diproses, dan Anda ingin mencegah UI menjadi tidak responsif selama pembaruan tersebut.
Sintaks:
const [isPending, startTransition] = useTransition();
Contoh:
import React, { useState, useTransition } from 'react';
function App() {
const [isPending, startTransition] = useTransition();
const [value, setValue] = useState('');
const [list, setList] = useState([]);
const handleChange = (e) => {
const inputValue = e.target.value;
setValue(inputValue);
startTransition(() => {
const newList = [];
for (let i = 0; i < 20000; i++) {
newList.push(inputValue);
}
setList(newList);
});
};
return (
{isPending ? Loading...
: null}
{list.map((item, index) => (
{item}
))}
);
}
export default App;
Dalam contoh ini, useTransition
digunakan untuk mengelola transisi saat memperbarui daftar yang besar. startTransition
menandai pembaruan state sebagai transisi, yang memungkinkan React memprioritaskan pembaruan tersebut dan menjaga UI tetap responsif.
Tips dan Trik:
- Gunakan
useTransition
untuk pembaruan state yang mahal atau lambat. - Gunakan
isPending
untuk menampilkan indikator loading atau UI transisi lainnya.
12. useDeferredValue
: Menunda Pembaruan Kurang Penting
useDeferredValue
memungkinkan Anda menunda pembaruan nilai yang kurang penting. Ini berguna ketika Anda memiliki nilai yang memicu pembaruan besar-besaran dan Anda ingin menjaga UI tetap responsif dengan menunda pembaruan yang kurang penting.
Sintaks:
const deferredValue = useDeferredValue(value, { timeoutMs: 10000 });
Contoh:
import React, { useState, useDeferredValue } from 'react';
function App() {
const [value, setValue] = useState('');
const deferredValue = useDeferredValue(value, { timeoutMs: 2000 });
const handleChange = (e) => {
setValue(e.target.value);
};
return (
);
}
function SlowList({ value }) {
const items = [];
for (let i = 0; i < 1000; i++) {
items.push({value});
}
return {items};
}
export default App;
Dalam contoh ini, useDeferredValue
digunakan untuk menunda pembaruan daftar yang besar. Nilai value
segera diperbarui, tetapi pembaruan daftar ditunda sampai React memiliki waktu untuk memprosesnya. Ini menjaga UI tetap responsif saat pengguna mengetik.
Tips dan Trik:
- Gunakan
useDeferredValue
untuk nilai yang memicu pembaruan besar-besaran. - Sesuaikan
timeoutMs
untuk mengontrol seberapa lama pembaruan ditunda.
13. useId
: Membuat ID Unik
useId
memungkinkan Anda menghasilkan ID unik yang stabil di server dan klien. Ini berguna untuk membuat atribut ID yang unik untuk elemen HTML, terutama dalam situasi rendering sisi server (SSR).
Sintaks:
const id = useId();
Contoh:
import React, { useId } from 'react';
function MyComponent() {
const id = useId();
return (
);
}
export default MyComponent;
Dalam contoh ini, useId
digunakan untuk menghasilkan ID unik untuk input dan label. Ini memastikan bahwa atribut for
pada label cocok dengan atribut id
pada input, yang penting untuk aksesibilitas.
Tips dan Trik:
- Gunakan
useId
untuk membuat ID unik untuk elemen HTML. - Ini sangat berguna dalam situasi rendering sisi server (SSR).
14. useSyncExternalStore
: Berlangganan ke Penyimpanan Eksternal
useSyncExternalStore
memungkinkan komponen React untuk berlangganan ke penyimpanan data eksternal, seperti yang dikelola oleh library pihak ketiga. Ini berguna ketika Anda perlu mengintegrasikan React dengan penyimpanan data yang ada yang tidak dikelola oleh React itu sendiri.
Sintaks:
const snapshot = useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);
Contoh:
import React, { useState, useEffect } from 'react';
import { useSyncExternalStore } from 'react';
// Contoh penyimpanan eksternal sederhana
const createStore = (initialValue) => {
let value = initialValue;
let listeners = [];
const subscribe = (listener) => {
listeners = [...listeners, listener];
return () => {
listeners = listeners.filter(l => l !== listener);
};
};
const getSnapshot = () => value;
const set = (newValue) => {
value = newValue;
listeners.forEach(listener => listener());
};
return { subscribe, getSnapshot, set };
};
// Membuat instance dari penyimpanan eksternal
const myStore = createStore(0);
function Counter() {
// Berlangganan ke penyimpanan eksternal menggunakan useSyncExternalStore
const count = useSyncExternalStore(myStore.subscribe, myStore.getSnapshot);
return (
Count: {count}
);
}
export default Counter;
Dalam contoh ini, useSyncExternalStore
digunakan untuk berlangganan ke penyimpanan eksternal sederhana. Setiap kali nilai dalam penyimpanan eksternal berubah, komponen Counter
akan dirender ulang dengan nilai terbaru.
Tips dan Trik:
- Gunakan
useSyncExternalStore
untuk mengintegrasikan React dengan penyimpanan data eksternal. - Pastikan fungsi
subscribe
mengembalikan fungsi untuk membatalkan langganan. - Pastikan fungsi
getSnapshot
mengembalikan snapshot data terbaru dari penyimpanan eksternal.
15. useInsertionEffect
: Memanipulasi DOM sebelum Layout
useInsertionEffect
adalah hook yang memungkinkan Anda memanipulasi DOM sebelum browser menghitung layout. Ini berguna untuk optimasi performa ketika memodifikasi gaya atau properti DOM lainnya yang memengaruhi layout.
Sintaks:
useInsertionEffect(() => {
// Manipulasi DOM
return () => {
// Fungsi pembersihan (opsional)
};
}, [dependencies]);
Contoh:
import React, { useRef, useInsertionEffect } from 'react';
function MyComponent() {
const styleRef = useRef(null);
useInsertionEffect(() => {
if (styleRef.current) {
// Memodifikasi gaya sebelum layout dihitung
styleRef.current.textContent = `
.my-element {
color: blue;
}
`;
}
}, []);
return (
Halo, dunia!
);
}
export default MyComponent;
Dalam contoh ini, useInsertionEffect
digunakan untuk memasukkan gaya ke dalam elemen <style>
sebelum layout dihitung. Ini memastikan bahwa gaya diterapkan secepat mungkin dan menghindari flicker pada UI.
Tips dan Trik:
- Gunakan
useInsertionEffect
untuk memodifikasi gaya atau properti DOM lainnya yang memengaruhi layout. - Pastikan fungsi pembersihan membatalkan perubahan yang dilakukan