Thursday

19-06-2025 Vol 19

Fixing Vite HMR Issues in React by Splitting Your Auth Context

Mengatasi Masalah HMR Vite di React dengan Memisahkan Auth Context

Hot Module Replacement (HMR) adalah fitur penting dalam pengembangan modern yang memungkinkan Anda melihat perubahan pada kode Anda secara instan di browser tanpa melakukan refresh penuh. Vite, sebagai bundler yang sangat cepat, memanfaatkan HMR untuk memberikan pengalaman pengembang yang luar biasa. Namun, terkadang, HMR bisa menjadi rumit, terutama dalam aplikasi React yang besar dengan konteks yang kompleks seperti Auth Context. Artikel ini akan membahas masalah umum HMR yang terkait dengan Auth Context di React dan memberikan solusi langkah demi langkah tentang cara memperbaikinya dengan memisahkan Auth Context Anda.

Daftar Isi

  1. Pendahuluan: Mengapa HMR Penting dan Masalah yang Mungkin Timbul
  2. Memahami Masalah HMR dengan Auth Context
  3. Solusi: Memisahkan Auth Context Anda
  4. Keuntungan Memisahkan Auth Context
  5. Studi Kasus: Contoh Implementasi
  6. Tips Tambahan untuk Mengoptimalkan HMR di React
  7. Kesimpulan

Pendahuluan: Mengapa HMR Penting dan Masalah yang Mungkin Timbul

Hot Module Replacement (HMR) memungkinkan Anda memperbarui modul aplikasi yang sedang berjalan tanpa kehilangan status aplikasi. Ini berarti Anda dapat membuat perubahan pada kode Anda dan melihatnya langsung di browser tanpa perlu refresh halaman secara manual. Ini mempercepat siklus pengembangan secara signifikan dan meningkatkan produktivitas. Vite, dengan arsitekturnya yang berorientasi pada kecepatan, menawarkan HMR yang sangat cepat, yang membuatnya menjadi pilihan populer untuk pengembangan React.

Namun, ada beberapa faktor yang dapat menyebabkan masalah HMR. Salah satu faktor yang paling umum adalah konteks yang besar dan sering berubah. Dalam aplikasi React, konteks digunakan untuk berbagi data di seluruh pohon komponen tanpa harus secara manual meneruskannya melalui setiap level. Auth Context, yang biasanya menyimpan informasi autentikasi pengguna, adalah contoh umum dari konteks yang dapat menyebabkan masalah HMR jika sering berubah.

Ketika HMR mendeteksi perubahan dalam modul yang menyediakan konteks, ia akan mencoba untuk memperbarui semua komponen yang berlangganan konteks tersebut. Jika konteks besar dan banyak komponen berlangganan ke sana, proses pembaruan bisa memakan waktu dan menyebabkan refresh penuh halaman, yang mengalahkan tujuan HMR.

Memahami Masalah HMR dengan Auth Context

Masalah HMR dengan Auth Context biasanya terjadi karena beberapa alasan:

  1. Konteks Terlalu Besar: Auth Context mungkin menyimpan banyak data yang tidak perlu diperbarui setiap kali perubahan terjadi pada informasi autentikasi.
  2. Terlalu Banyak Komponen yang Berlangganan: Banyak komponen mungkin berlangganan Auth Context, bahkan jika mereka hanya membutuhkan sebagian kecil dari data yang disediakan.
  3. Perubahan yang Sering: Beberapa bagian dari Auth Context mungkin berubah lebih sering daripada yang lain. Misalnya, status autentikasi (masuk/keluar) mungkin berubah lebih sering daripada informasi profil pengguna.

Sebagai contoh, pertimbangkan Auth Context sederhana yang menyimpan informasi pengguna dan fungsi untuk masuk dan keluar:


// AuthContext.jsx
import React, { createContext, useState, useEffect } from 'react';

const AuthContext = createContext();

export const AuthProvider = ({ children }) => {
  const [user, setUser] = useState(null);
  const [isLoading, setIsLoading] = useState(true);

  useEffect(() => {
    // Simulasi pengambilan data pengguna dari localStorage atau API
    setTimeout(() => {
      const storedUser = localStorage.getItem('user');
      if (storedUser) {
        setUser(JSON.parse(storedUser));
      }
      setIsLoading(false);
    }, 1000);
  }, []);

  const login = async (credentials) => {
    // Simulasi login
    await new Promise(resolve => setTimeout(resolve, 1000));
    const fakeUser = { id: 1, name: 'John Doe', email: 'john.doe@example.com' };
    setUser(fakeUser);
    localStorage.setItem('user', JSON.stringify(fakeUser));
  };

  const logout = () => {
    setUser(null);
    localStorage.removeItem('user');
  };

  const value = {
    user,
    isLoading,
    login,
    logout,
  };

  return (
    <AuthContext.Provider value={value}>
      {children}
    </AuthContext.Provider>
  );
};

export const useAuth = () => React.useContext(AuthContext);

Jika Anda mengubah fungsi `login` atau `logout`, HMR akan mencoba memperbarui semua komponen yang menggunakan `useAuth`, bahkan jika mereka hanya menggunakan data `user` dan tidak memerlukan fungsi-fungsi tersebut. Ini dapat menyebabkan refresh penuh yang tidak perlu.

Solusi: Memisahkan Auth Context Anda

Solusi untuk masalah ini adalah memisahkan Auth Context Anda menjadi beberapa konteks yang lebih kecil. Dengan memisahkan konteks berdasarkan frekuensi perubahan dan penggunaan data, Anda dapat meminimalkan dampak perubahan pada HMR.

Langkah 1: Mengidentifikasi Bagian yang Berubah Sering

Langkah pertama adalah mengidentifikasi bagian dari Auth Context Anda yang berubah paling sering. Dalam contoh kita, fungsi `login` dan `logout` mungkin berubah lebih sering daripada data `user` atau status `isLoading`. Jadi, kita dapat memisahkan fungsi-fungsi ini ke dalam konteks yang terpisah.

Langkah 2: Membuat Konteks Baru untuk Bagian yang Stabil

Selanjutnya, kita akan membuat konteks baru untuk data yang relatif stabil, seperti informasi `user` dan status `isLoading`. Kita akan menyebutnya `UserContext`.


// UserContext.jsx
import React, { createContext, useState, useEffect, useContext } from 'react';

const UserContext = createContext();

export const UserProvider = ({ children }) => {
  const [user, setUser] = useState(null);
  const [isLoading, setIsLoading] = useState(true);

  useEffect(() => {
    // Simulasi pengambilan data pengguna dari localStorage atau API
    setTimeout(() => {
      const storedUser = localStorage.getItem('user');
      if (storedUser) {
        setUser(JSON.parse(storedUser));
      }
      setIsLoading(false);
    }, 1000);
  }, []);

  const value = {
    user,
    isLoading,
  };

  return (
    <UserContext.Provider value={value}>
      {children}
    </UserContext.Provider>
  );
};

export const useUser = () => useContext(UserContext);

Kemudian, kita akan membuat konteks lain yang disebut `AuthActionsContext` untuk fungsi `login` dan `logout`.


// AuthActionsContext.jsx
import React, { createContext, useContext } from 'react';
import { useUser } from './UserContext';

const AuthActionsContext = createContext();

export const AuthActionsProvider = ({ children }) => {
  const { setUser } = useUserContextValue(); // Menggunakan UserContext untuk mengakses setUser

  const login = async (credentials) => {
    // Simulasi login
    await new Promise(resolve => setTimeout(resolve, 1000));
    const fakeUser = { id: 1, name: 'John Doe', email: 'john.doe@example.com' };
    setUser(fakeUser);
    localStorage.setItem('user', JSON.stringify(fakeUser));
  };

  const logout = () => {
    setUser(null);
    localStorage.removeItem('user');
  };

  const value = {
    login,
    logout,
  };

  return (
    <AuthActionsContext.Provider value={value}>
      {children}
    </AuthActionsContext.Provider>
  );
};

export const useAuthActions = () => useContext(AuthActionsContext);

// Custom hook untuk mengakses nilai dari UserContext
const useUserContextValue = () => {
    const [user, setUser] = React.useState(null);
    const [isLoading, setIsLoading] = React.useState(true);

    React.useEffect(() => {
      // Simulasi pengambilan data pengguna dari localStorage atau API
      setTimeout(() => {
        const storedUser = localStorage.getItem('user');
        if (storedUser) {
          setUser(JSON.parse(storedUser));
        }
        setIsLoading(false);
      }, 1000);
    }, []);

    return {
      user,
      setUser, // Mengembalikan setUser untuk digunakan di AuthActionsProvider
      isLoading,
      setIsLoading
    };
  };

Langkah 3: Memperbarui Komponen untuk Menggunakan Konteks yang Dipisahkan

Sekarang, kita perlu memperbarui komponen kita untuk menggunakan konteks yang dipisahkan. Alih-alih menggunakan `useAuth`, kita akan menggunakan `useUser` untuk mengakses informasi `user` dan `isLoading`, dan `useAuthActions` untuk mengakses fungsi `login` dan `logout`.


// Contoh komponen yang diperbarui
import React from 'react';
import { useUser } from './UserContext';
import { useAuthActions } from './AuthActionsContext';

const Profile = () => {
  const { user, isLoading } = useUser();
  const { logout } = useAuthActions();

  if (isLoading) {
    return <p>Loading...</p>;
  }

  if (!user) {
    return <p>Please login.</p>;
  }

  return (
    <div>
      <h2>Welcome, {user.name}!</h2>
      <p>Email: {user.email}</p>
      <button onClick={logout}>Logout</button>
    </div>
  );
};

export default Profile;

Pastikan untuk membungkus aplikasi Anda dengan kedua provider konteks:


// App.jsx
import React from 'react';
import { UserProvider } from './UserContext';
import { AuthActionsProvider } from './AuthActionsContext';
import Profile from './Profile';

const App = () => {
  return (
    <UserProvider>
      <AuthActionsProvider>
        <Profile />
      </AuthActionsProvider>
    </UserProvider>
  );
};

export default App;

Langkah 4: Menguji Perubahan HMR

Setelah Anda memisahkan Auth Context Anda dan memperbarui komponen Anda, uji perubahan HMR Anda. Coba ubah fungsi `login` atau `logout` dan pastikan bahwa hanya komponen yang menggunakan `useAuthActions` yang diperbarui, dan bahwa komponen yang menggunakan `useUser` tidak terpengaruh. Ini akan membantu memastikan bahwa HMR bekerja dengan benar dan Anda tidak mengalami refresh penuh yang tidak perlu.

Keuntungan Memisahkan Auth Context

Memisahkan Auth Context Anda menawarkan beberapa keuntungan:

  1. Peningkatan Kinerja HMR: Dengan memisahkan data yang sering berubah dari data yang stabil, Anda dapat mengurangi jumlah komponen yang perlu diperbarui oleh HMR, yang mengarah pada pembaruan yang lebih cepat dan lebih efisien.
  2. Peningkatan Modularitas: Memisahkan konteks Anda membuat kode Anda lebih modular dan mudah dipelihara. Setiap konteks memiliki tanggung jawab yang jelas, yang membuatnya lebih mudah untuk memahami dan mengubah kode Anda.
  3. Penggunaan Memori yang Lebih Efisien: Dengan hanya menyediakan data yang diperlukan untuk setiap komponen, Anda dapat mengurangi penggunaan memori dan meningkatkan kinerja aplikasi Anda secara keseluruhan.

Studi Kasus: Contoh Implementasi

Mari kita pertimbangkan sebuah aplikasi e-commerce. Aplikasi ini memiliki Auth Context yang menyimpan informasi pengguna, status login, fungsi untuk masuk dan keluar, dan data keranjang belanja. Data keranjang belanja sering berubah ketika pengguna menambahkan atau menghapus item dari keranjang mereka.

Untuk meningkatkan kinerja HMR, kita dapat memisahkan Auth Context menjadi tiga konteks:

  1. UserContext: Menyimpan informasi pengguna dan status login.
  2. AuthActionsContext: Menyediakan fungsi untuk masuk dan keluar.
  3. CartContext: Menyimpan data keranjang belanja.

Dengan memisahkan konteks ini, kita dapat memastikan bahwa perubahan pada data keranjang belanja tidak memicu pembaruan pada komponen yang hanya menggunakan informasi pengguna atau fungsi login/logout. Ini akan meningkatkan kinerja HMR secara signifikan dan membuat siklus pengembangan lebih efisien.

Tips Tambahan untuk Mengoptimalkan HMR di React

Berikut adalah beberapa tips tambahan untuk mengoptimalkan HMR di React:

  1. Hindari Import Siklik: Import siklik dapat menyebabkan masalah HMR. Pastikan bahwa modul Anda tidak saling mengimpor dalam lingkaran.
  2. Gunakan React.memo: `React.memo` adalah komponen higher-order yang dapat membantu Anda mengoptimalkan kinerja dengan mencegah komponen dirender ulang jika prop-nya tidak berubah. Ini dapat membantu mengurangi jumlah komponen yang perlu diperbarui oleh HMR.
  3. Gunakan useCallback dan useMemo: `useCallback` dan `useMemo` adalah hooks yang dapat membantu Anda mengoptimalkan kinerja dengan memorisasi fungsi dan nilai. Ini dapat membantu mencegah pembaruan yang tidak perlu pada prop komponen.
  4. Periksa Konfigurasi Vite: Pastikan bahwa konfigurasi Vite Anda dioptimalkan untuk HMR. Anda dapat menyesuaikan opsi seperti `hmr.overlay` dan `hmr.clientPort` untuk meningkatkan kinerja HMR.
  5. Gunakan Plugin HMR: Ada beberapa plugin HMR yang tersedia yang dapat membantu Anda meningkatkan kinerja HMR di React. Misalnya, plugin `react-refresh-webpack-plugin` (meskipun namanya webpack, beberapa prinsipnya bisa diterapkan dalam pemikiran yang sama untuk Vite) dapat membantu Anda mempertahankan status komponen saat HMR terjadi.

Kesimpulan

HMR adalah fitur yang sangat berharga untuk pengembangan React yang memungkinkan Anda melihat perubahan pada kode Anda secara instan tanpa refresh penuh. Namun, masalah HMR dapat terjadi, terutama dengan konteks yang besar dan sering berubah seperti Auth Context. Dengan memisahkan Auth Context Anda menjadi beberapa konteks yang lebih kecil, Anda dapat meningkatkan kinerja HMR, meningkatkan modularitas kode Anda, dan mengoptimalkan penggunaan memori. Dengan mengikuti langkah-langkah dan tips yang diuraikan dalam artikel ini, Anda dapat mengatasi masalah HMR di aplikasi React Anda dan menikmati pengalaman pengembangan yang lebih lancar dan efisien.

“`

omcoding

Leave a Reply

Your email address will not be published. Required fields are marked *