10MenengahPertemuan ke-10

Lifecycle & Advanced Hooks

Memahami React lifecycle, custom hooks, dan advanced hook patterns.

Topik Pembelajaran

  • Component lifecycle dengan class components
  • useEffect lifecycle
  • useCallback & useMemo
  • Custom hooks creation
  • useContext untuk prop drilling
  • Hook best practices

Referensi & Sumber Daya

Lifecycle & Advanced Hooks

Tujuan Pembelajaran

  • Memahami lifecycle component dengan useEffect
  • Menggunakan useCallback, useMemo untuk optimasi
  • Membuat custom hooks yang reusable

A. useEffect untuk Data Fetching

jsx
import { useState, useEffect } from 'react'; import { View, Text, FlatList, ActivityIndicator, StyleSheet } from 'react-native'; export default function App() { const [users, setUsers] = useState([]); const [loading, setLoading] = useState(true); useEffect(() => { // Fetch data saat component mount fetchUsers(); }, []); // [] = hanya jalan sekali const fetchUsers = async () => { try { const res = await fetch('https://jsonplaceholder.typicode.com/users'); const data = await res.json(); setUsers(data); } catch (err) { console.error(err); } finally { setLoading(false); } }; if (loading) return ( <View style={styles.center}> <ActivityIndicator size="large" color="#6200ee" /> </View> ); return ( <View style={styles.container}> <Text style={styles.title}>Daftar User dari API</Text> <FlatList data={users} keyExtractor={item => item.id.toString()} renderItem={({ item }) => ( <View style={styles.card}> <Text style={styles.name}>{item.name}</Text> <Text style={styles.email}>{item.email}</Text> </View> )} /> </View> ); } const styles = StyleSheet.create({ container: { flex: 1, padding: 16, paddingTop: 50 }, center: { flex: 1, justifyContent: 'center', alignItems: 'center' }, title: { fontSize: 24, fontWeight: 'bold', marginBottom: 16 }, card: { backgroundColor: '#f5f5f5', padding: 16, borderRadius: 10, marginBottom: 8 }, name: { fontSize: 16, fontWeight: 'bold' }, email: { fontSize: 13, color: '#666' }, });

B. useEffect Cleanup (Timer & Subscription)

jsx
useEffect(() => { const timer = setInterval(() => { console.log('Timer berjalan...'); }, 1000); // Cleanup: hentikan timer saat component unmount return () => clearInterval(timer); }, []);

C. Custom Hook: useFetch

jsx
// hooks/useFetch.js import { useState, useEffect } from 'react'; export function useFetch(url) { const [data, setData] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); useEffect(() => { const fetchData = async () => { try { const res = await fetch(url); const json = await res.json(); setData(json); } catch (err) { setError(err.message); } finally { setLoading(false); } }; fetchData(); }, [url]); return { data, loading, error }; } // Penggunaan di component: // const { data, loading, error } = useFetch('https://api.example.com/data');

D. useMemo & useCallback

jsx
import { useState, useMemo, useCallback } from 'react'; function App() { const [items, setItems] = useState([]); const [search, setSearch] = useState(''); // useMemo: hitung ulang hanya jika items/search berubah const filteredItems = useMemo(() => { return items.filter(item => item.name.toLowerCase().includes(search.toLowerCase()) ); }, [items, search]); // useCallback: fungsi tidak dibuat ulang setiap render const handleDelete = useCallback((id) => { setItems(prev => prev.filter(item => item.id !== id)); }, []); return (/* ... */); }

E. Latihan Mandiri

  1. Buat aplikasi yang fetch data dari API publik (pilih: posts/pokemon/products)
  2. Gunakan custom hook useFetch untuk data fetching
  3. Tampilkan loading indicator dan error handling
  4. Implementasikan pull-to-refresh (RefreshControl)
  5. Screenshot dan kumpulkan source code