Penggunaan React useLayoutEffect.



useLayoutEffect adalah hook di React yang mirip dengan useEffect, tetapi dijalankan secara sinkron setelah React melakukan mutasi DOM dan sebelum browser melakukan painting. Ini berguna ketika Anda perlu membaca atau memodifikasi layout DOM secara sinkron sebelum browser menampilkan perubahan ke layar. Berikut penjelasan lengkapnya:
1. Sintaks Dasar
useLayoutEffect(() => {
// Kode efek samping di sini
return () => {
// Cleanup (opsional)
};
}, [dependencies]); // Dependency array
2. Perbedaan useLayoutEffect vs useEffect
Kriteria | useLayoutEffect | useEffect |
---|---|---|
Waktu Eksekusi | Setelah mutasi DOM, sebelum browser paint | Setelah mutasi DOM, setelah browser paint |
Penggunaan | Untuk operasi yang memengaruhi tampilan (misal: ukuran/posisi DOM) | Untuk efek samping umum (fetch data, subscriptions) |
Blokir Paint | Ya (jika kode berat) | Tidak |
SSR | Tidak direkomendasikan (menyebabkan peringatan) | Aman di SSR |
3. Kapan Menggunakan useLayoutEffect?
- Membaca/mengukur DOM (misal: ukuran elemen, posisi scroll).
- Memodifikasi DOM secara sinkron untuk menghindari "flicker" atau perubahan visual yang terlihat pengguna.
- Animasi atau transisi yang memerlukan pembaruan DOM sebelum paint.
4. Contoh Penggunaan
a. Mengukur Ukuran Elemen
import { useLayoutEffect, useRef, useState } from 'react';
function MeasureElement() {
const ref = useRef();
const [size, setSize] = useState({ width: 0, height: 0 });
useLayoutEffect(() => {
// Ukur elemen setelah DOM diupdate
const { width, height } = ref.current.getBoundingClientRect();
setSize({ width, height });
}, []); // Jalankan sekali saat mount
return (
<div>
<div ref={ref} style={{ border: '1px solid red' }}>
Ukuran: {size.width}x{size.height}
</div>
</div>
);
}
b. Menyesuaikan Posisi Tooltip
function Tooltip({ text }) {
const tooltipRef = useRef();
const [position, setPosition] = useState({ top: 0, left: 0 });
useLayoutEffect(() => {
// Hitung posisi tooltip relatif terhadap parent
const parentRect = tooltipRef.current.parentElement.getBoundingClientRect();
const newPosition = {
top: parentRect.top - 30,
left: parentRect.left + parentRect.width / 2,
};
setPosition(newPosition);
}, [text]); // Jalankan ulang saat <code>text</code> berubah
return (
<div
ref={tooltipRef}
style={{
position: 'fixed',
top: position.top,
left: position.left,
}}
>
{text}
</div>
);
}
c. Auto-Scroll ke Bawah List
function ChatList({ messages }) {
const listRef = useRef();
useLayoutEffect(() => {
// Auto-scroll ke bawah saat pesan baru ditambahkan
listRef.current.scrollTop = listRef.current.scrollHeight;
}, [messages]);
return (
<div ref={listRef} style={{ height: '300px', overflowY: 'auto' }}>
{messages.map((msg) => (
<div key={msg.id}>{msg.text}</div>
))}
</div>
);
}
5. Peringatan Penting
-
Hindari Kode Berat di useLayoutEffect
Karena dijalankan sebelum browser paint, kode yang lambat akan memblokir tampilan visual hingga selesai.
Contoh buruk:useLayoutEffect(() => { // Kode berat (misal: loop ribuan iterasi) for (let i = 0; i < 100000; i++) { /* ... */ } }, []);
-
Masalah dengan Server-Side Rendering (SSR)
useLayoutEffect tidak bekerja di server. Jika digunakan di SSR, React akan memberi peringatan.
Solusi:- Gunakan useEffect untuk SSR.
- Atau, jalankan kode hanya di client dengan:
useLayoutEffect(() => { if (typeof window !== 'undefined') { // Kode khusus client } }, []);
6. Best Practices
-
Gunakan useEffect Sebagai Default
Beralih ke useLayoutEffect hanya jika ada masalah visual yang perlu diatasi secara sinkron. -
Optimasi Operasi DOM
Pastikan operasi di useLayoutEffect cepat dan tidak menghambat paint. -
Hindari State Update di useLayoutEffect
Jika memungkinkan, gunakan untuk operasi DOM langsung, bukan update state yang memicu re-render.
Kapan Memilih useLayoutEffect?
- Saat Anda perlu membaca atau menulis DOM secara sinkron sebelum browser paint (misal: menghitung posisi tooltip).
- Untuk menghindari flicker saat perubahan DOM harus langsung terlihat (misal: animasi transisi).
Kesimpulan
useLayoutEffect adalah alat yang powerful untuk kasus khusus di mana pembaruan DOM harus terjadi sebelum browser paint. Gunakan dengan bijak untuk menghindari masalah performa dan kompatibilitas! 🚨