ReactHooksAdvanced

Pola React Hooks Tingkat Lanjut

19 Desember 2025
4 min

Pelajari pola lanjutan untuk React Hooks seperti hook khusus, useReducer untuk keadaan kompleks, dan teknik pengoptimalan yang jarang diketahui oleh pengembang.

Pola React Hooks Tingkat Lanjut

Pendahuluan

React Hooks telah merevolusi cara kami menulis komponen React sejak diperkenalkan di versi 16.8. Namun, banyak developer yang masih menggunakan hook hanya pada tingkat permukaan, tanpa menyadari pola kuat yang diaktifkannya.

Artikel ini mengeksplorasi pola React Hooks tingkat lanjut yang dapat secara signifikan meningkatkan kualitas, kinerja, dan skalabilitas aplikasi React Anda.


Hook Kustom yang Kuat

  • useFetch dengan Manajemen Cache

import { useState, useEffect, useRef } dari "react";

const useFetch = (url, opsi = {}) => {
  const [data, setData] = useState(null);
  const [memuat, setLoading] = useState(true);
  const [kesalahan, setError] = useState(null);
  const cache = useRef({});

  gunakanEffect(() => {
    jika (!url) kembali;

    const mengambilData = async() => {
      setLoading(benar);
      setError(nol);

      // Mekanisme cache
      if (cache.saat ini[url]) {
        setData(cache.saat ini[url]);
        setLoading(salah);
        kembali;
      }

      coba {
        const respon = menunggu pengambilan(url, opsi);
        if (!response.ok) throw new Error("Respon jaringan tidak baik");

        hasil const = menunggu respon.json();
        cache.current[url] = hasil;
        setData(hasil);
      } menangkap (salah) {
        setError(err.pesan);
      } akhirnya {
        setLoading(salah);
      }
    };

    ambilData();
  }, [url]);

  return { data, memuat, kesalahan };
};

2. useLocalStorage dengan Serialisasi

impor { useState } dari "react";

const useLocalStorage = (kunci, Nilai awal) => {
  const [nilai tersimpan, setnilai tersimpan] = useState(() => {
    coba {
      const item = window.localStorage.getItem(kunci);
      barang kembalian? JSON.parse(item): Nilai awal;
    } tangkapan (kesalahan) {
      console.error(`Kesalahan membaca kunci Penyimpanan lokal "${key}":`, kesalahan);
      kembalikan Nilai Awal;
    }
  });

  const setValue = (nilai) => {
    coba {
      const valueToStore = nilai instanceof Fungsi? nilai(nilai tersimpan): nilai;
      setStoredValue(nilaiToStore);
      window.localStorage.setItem(kunci, JSON.stringify(valueToStore));
    } tangkapan (kesalahan) {
      console.error(`Kesalahan saat menyetel kunci Penyimpanan lokal "${key}":`, kesalahan);
    }
  };

  kembali [nilai tersimpan, nilai set];
};

useReducer untuk Manajemen Status Kompleks

Aplikasi Todo Tingkat Lanjut dengan useReducer

const todoReducer = (state, action) => {
  beralih (tipe tindakan) {
    kasus "ADD_TODO":
      kembali {
        ...negara bagian,
        semua yang harus dilakukan: [
          ...negara.todos,
          {
            id: Tanggal.sekarang(),
            teks: aksi.payload,
            selesai: salah,
            dibuatPada: Tanggal baru().toISOString(),
          },
        ],
      };

    kasus "TOGGLE_TODO":
      kembali {
        ...negara bagian,
        semua yang harus dilakukan: state.todos.map((todo) =>
          todo.id === aksi.payload
            ? { ...todo, selesai: !todo.selesai }
            : melakukan
        ),
      };

    kasus "DELETE_TODO":
      kembali {
        ...negara bagian,
        todos: state.todos.filter((todo) => todo.id !== action.payload),
      };

    kasus "SET_FILTER":
      return { ...state, filter: action.payload };

    kasus "BULK_UPDATE":
      kembali {
        ...negara bagian,
        hal yang harus dilakukan: state.todos.map((hal yang harus dilakukan) => ({
          ... yang harus dilakukan,
          ...aksi.payload.pembaruan,
        })),
      };

    bawaan:
      negara bagian kembali;
  }
};

const useTodo = () => {
  const [negara bagian, pengiriman] = useReducer(todoReducer, {
    semua yang harus dilakukan: [],
    menyaring: "semua",
  });

  const filteredTodos = state.todos.filter((todo) => {
    beralih (status.filter) {
      kasus "selesai":
        return todo.selesai;
      kasus "aktif":
        kembali !todo.selesai;
      bawaan:
        kembali benar;
    }
  });

  kembali {
    semua yang dilakukan: difilterTodos,
    addTodo: (teks) => pengiriman({ ketik: "ADD_TODO", muatan: teks }),
    toggleTodo: (id) => pengiriman({ ketik: "TOGGLE_TODO", muatan: id }),
    deleteTodo: (id) => pengiriman({ ketik: "DELETE_TODO", muatan: id }),
    setFilter: (filter) => pengiriman({ ketik: "SET_FILTER", muatan: filter }),
  };
};

Teknik Optimasi yang Jarang Diketahui

1. useMemo dengan Perbandingan Mendalam

impor { useMemo, useRef } dari "react";

const useDeepCompareMemo = (pabrik, dependensi) => {
  const ref = gunakanRef();
  const serializedDeps = JSON.stringify(dependensi);

  kembalikan useMemo(() => {
    if (ref.saat ini !== serializedDeps) {
      ref.saat ini = serializedDeps;
      kembalikan pabrik();
    }
  }, [serializedDeps, pabrik]);
};

2. useCallback dengan Injeksi Ketergantungan

impor { useCallback, useEffect, useRef } dari "react";

const useStableCallback = (panggilan balik, dependensi = []) => {
  const callbackRef = useRef(panggilan balik);

  gunakanEffect(() => {
    callbackRef.current = panggilan balik;
  });

  kembalikan useCallback((...args) => {
    return callbackRef.saat ini(...args);
  }, dependensi);
};

Pola Tingkat Lanjut: Komponen Gabungan dengan Konteks

import { createContext, useContext, useState } dari "react";

const AccordionContext = buatContext();

const Akordeon = ({ anak, kelipatan = salah }) => {
  const [Item terbuka, setItem Terbuka] = useState([]);

  const toggleItem = (id) => {
    setOpenItems((sebelumnya) =>
      banyak
        ? sebelumnya.termasuk(id)
          ? sebelumnya.filter((i) => saya !== id)
          : [...sebelumnya, identitas]
        : sebelumnya.termasuk(id)
        ? []
        : [id]
    );
  };

  kembali (
    <AccordionContext.Provider value={{ openItems, toggleItem }}>
      {anak-anak}
    </AccordionContext.Penyedia>
  );
};

Pola: Mesin Status dengan useReducer

const createMachine = (config) => (state, action) => {
  const saat ini = config.states[state.state];

  if (saat ini?.transisi?.[action.type]) {
    const transisi = arus.transisi[tindakan.tipe];
    kembali {
      status: transisi.target,
      konteks:
        transisi.aksi?.(status.konteks, tindakan) ?? negara.konteks,
    };
  }

  negara bagian kembali;
};

Praktik dan Kesalahan Terbaik

1. Array Ketergantungan Kait

// ❌ Salah
useEffect(() => {}, [props.pengguna]);

// ✅ Benar
useEffect(() => {}, [props.pengguna.id]);

2. Komposisi Kait Khusus

const useUserDashboard = (userId) => {
  const pengguna = useUser(userId);
  const posting = useUserPosts(userId);
  pemberitahuan const = useUserNotifications(userId);

  const sedang Memuat =
    pengguna.memuat || posting.memuat || notifikasi.memuat;

  kembali {
    pengguna: pengguna.data,
    postingan: postingan.data,
    notifikasi: notifikasi.data,
    sedang memuat,
  };
};

3. Penanganan Kesalahan dengan Hooks

import { useCallback, useEffect, useState } from "react";

const useErrorHandler = () => {
  const [kesalahan, setError] = useState(null);

  const handleError = useCallback((err) => {
    console.error("Kesalahan aplikasi:",err);
    setError(salah);
  }, []);

  gunakanEffect(() => {
    jika (kesalahan) melempar kesalahan;
  }, [kesalahan]);

  kembalikan handleError;
};

Kesimpulan

Pola React Hooks tingkat lanjut membuka cara ampuh untuk membangun aplikasi yang dapat dikelola, berperforma, dan dapat diskalakan.

Poin Penting

  • Hook khusus meningkatkan penggunaan kembali logika dan pemisahan masalah

  • useReducer menyederhanakan manajemen status yang kompleks

  • Memoisasi tingkat lanjut meningkatkan kinerja

  • Komponen gabungan memungkinkan API yang fleksibel

  • Mesin status menciptakan transisi status yang dapat diprediksi

Dengan menguasai pola-pola ini, Anda akan menjadi developer React yang lebih percaya diri dan efektif.