Bahasa Indonesia

Kuasai React Error Boundaries untuk membangun aplikasi tangguh dan ramah pengguna. Pelajari praktik terbaik, implementasi, dan strategi penanganan error tingkat lanjut.

React Error Boundaries: Teknik Penanganan Kesalahan yang Anggun untuk Aplikasi yang Kuat

Di dunia pengembangan web yang dinamis, membuat aplikasi yang kuat dan ramah pengguna adalah yang terpenting. React, sebuah pustaka JavaScript populer untuk membangun antarmuka pengguna, menyediakan mekanisme yang kuat untuk menangani kesalahan secara anggun: Error Boundaries. Panduan komprehensif ini membahas konsep Error Boundaries, menjelajahi tujuan, implementasi, dan praktik terbaik untuk membangun aplikasi React yang tangguh.

Memahami Kebutuhan akan Error Boundaries

Komponen React, seperti kode pada umumnya, rentan terhadap kesalahan. Kesalahan ini dapat berasal dari berbagai sumber, termasuk:

Tanpa penanganan kesalahan yang tepat, kesalahan dalam komponen React dapat merusak seluruh aplikasi, yang mengakibatkan pengalaman pengguna yang buruk. Error Boundaries menyediakan cara untuk menangkap kesalahan ini dan mencegahnya menyebar ke atas pohon komponen, memastikan bahwa aplikasi tetap fungsional bahkan ketika komponen individual gagal.

Apa itu React Error Boundaries?

Error Boundaries adalah komponen React yang menangkap kesalahan JavaScript di mana pun di dalam pohon komponen turunannya, mencatat kesalahan tersebut, dan menampilkan UI fallback alih-alih pohon komponen yang rusak. Mereka bertindak sebagai jaring pengaman, mencegah kesalahan merusak seluruh aplikasi.

Karakteristik utama dari Error Boundaries:

Mengimplementasikan Error Boundaries

Mari kita ikuti proses pembuatan komponen Error Boundary dasar:

1. Membuat Komponen Error Boundary

Pertama, buat komponen kelas baru, misalnya, bernama ErrorBoundary:


import React from 'react';

class ErrorBoundary extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      hasError: false
    };
  }

  static getDerivedStateFromError(error) {
    // Perbarui state agar render berikutnya akan menampilkan UI fallback.
    return {
      hasError: true
    };
  }

  componentDidCatch(error, errorInfo) {
    // Anda juga bisa mencatat error ke layanan pelaporan kesalahan
    console.error("Caught error: ", error, errorInfo);
    // Contoh: logErrorToMyService(error, errorInfo);
  }

  render() {
    if (this.state.hasError) {
      // Anda dapat merender UI fallback kustom apa pun
      return (
        <div>
          <h2>Terjadi kesalahan.</h2>
          <details style={{ whiteSpace: 'pre-wrap' }}>
            {this.state.error && this.state.error.toString()}
            <br />
            {this.state.errorInfo.componentStack}
          </details>
        </div>
      );
    }

    return this.props.children; 
  }
}

export default ErrorBoundary;

Penjelasan:

2. Menggunakan Error Boundary

Untuk menggunakan Error Boundary, cukup bungkus komponen apa pun yang mungkin menimbulkan kesalahan dengan komponen ErrorBoundary:


import ErrorBoundary from './ErrorBoundary';

function MyComponent() {
  // Komponen ini mungkin menimbulkan kesalahan
  return (
    <ErrorBoundary>
      <PotentiallyBreakingComponent />
    </ErrorBoundary>
  );
}

export default MyComponent;

Jika PotentiallyBreakingComponent menimbulkan kesalahan, ErrorBoundary akan menangkapnya, mencatat kesalahan tersebut, dan merender UI fallback.

3. Contoh Ilustrasi

Pertimbangkan aplikasi e-commerce yang menampilkan informasi produk yang diambil dari server jarak jauh. Sebuah komponen, ProductDisplay, bertanggung jawab untuk merender detail produk. Namun, server terkadang dapat mengembalikan data yang tidak terduga, yang menyebabkan kesalahan rendering.


// ProductDisplay.js
import React from 'react';

function ProductDisplay({ product }) {
  // Simulasikan potensi kesalahan jika product.price bukan angka
  if (typeof product.price !== 'number') {
    throw new Error('Harga produk tidak valid');
  }

  return (
    <div>
      <h2>{product.name}</h2>
      <p>Harga: {product.price}</p>
      <img src={product.imageUrl} alt={product.name} />
    </div>
  );
}

export default ProductDisplay;

Untuk melindungi dari kesalahan semacam itu, bungkus komponen ProductDisplay dengan ErrorBoundary:


// App.js
import React from 'react';
import ErrorBoundary from './ErrorBoundary';
import ProductDisplay from './ProductDisplay';

function App() {
  const product = {
    name: 'Produk Contoh',
    price: 'Bukan Angka', // Data yang sengaja disalahkan
    imageUrl: 'https://example.com/image.jpg'
  };

  return (
    <div>
      <ErrorBoundary>
        <ProductDisplay product={product} />
      </ErrorBoundary>
    </div>
  );
}

export default App;

Dalam skenario ini, karena product.price sengaja diatur ke string alih-alih angka, komponen ProductDisplay akan menimbulkan kesalahan. ErrorBoundary akan menangkap kesalahan ini, mencegah seluruh aplikasi rusak, dan menampilkan UI fallback alih-alih komponen ProductDisplay yang rusak.

4. Error Boundaries dalam Aplikasi Internasionalisasi

Saat membangun aplikasi untuk audiens global, pesan kesalahan harus dilokalkan untuk memberikan pengalaman pengguna yang lebih baik. Error Boundaries dapat digunakan bersama dengan pustaka internasionalisasi (i18n) untuk menampilkan pesan kesalahan yang diterjemahkan.


// ErrorBoundary.js (dengan dukungan i18n)
import React from 'react';
import { useTranslation } from 'react-i18next'; // Dengan asumsi Anda menggunakan react-i18next

class ErrorBoundary extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      hasError: false,
      error: null,
      errorInfo: null,
    };
  }

  static getDerivedStateFromError(error) {
    return {
      hasError: true,
      error: error,
    };
  }

  componentDidCatch(error, errorInfo) {
    console.error("Caught error: ", error, errorInfo);
    this.setState({errorInfo: errorInfo});
  }

  render() {
    if (this.state.hasError) {
      return (
        <FallbackUI error={this.state.error} errorInfo={this.state.errorInfo}/>
      );
    }

    return this.props.children;
  }
}

const FallbackUI = ({error, errorInfo}) => {
  const { t } = useTranslation();

  return (
    <div>
      <h2>{t('error.title')}</h2>
      <p>{t('error.message')}</p>
      <details style={{ whiteSpace: 'pre-wrap' }}>
        {error && error.toString()}<br />
        {errorInfo?.componentStack}
      </details>
    </div>
  );
}


export default ErrorBoundary;

Dalam contoh ini, kita menggunakan react-i18next untuk menerjemahkan judul dan pesan kesalahan di UI fallback. Fungsi t('error.title') dan t('error.message') akan mengambil terjemahan yang sesuai berdasarkan bahasa yang dipilih pengguna.

5. Pertimbangan untuk Server-Side Rendering (SSR)

Saat menggunakan Error Boundaries dalam aplikasi yang di-render di sisi server, sangat penting untuk menangani kesalahan dengan tepat untuk mencegah server rusak. Dokumentasi React merekomendasikan agar Anda menghindari penggunaan Error Boundaries untuk pulih dari kesalahan rendering di server. Sebagai gantinya, tangani kesalahan sebelum merender komponen, atau render halaman kesalahan statis di server.

Praktik Terbaik Menggunakan Error Boundaries

Strategi Penanganan Kesalahan Tingkat Lanjut

1. Mekanisme Coba Ulang (Retry)

Dalam beberapa kasus, mungkin dimungkinkan untuk pulih dari kesalahan dengan mencoba ulang operasi yang menyebabkannya. Misalnya, jika permintaan jaringan gagal, Anda dapat mencobanya lagi setelah jeda singkat. Error Boundaries dapat digabungkan dengan mekanisme coba ulang untuk memberikan pengalaman pengguna yang lebih tangguh.


// ErrorBoundaryWithRetry.js
import React from 'react';

class ErrorBoundaryWithRetry extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      hasError: false,
      retryCount: 0,
    };
  }

  static getDerivedStateFromError(error) {
    return {
      hasError: true,
    };
  }

  componentDidCatch(error, errorInfo) {
    console.error("Caught error: ", error, errorInfo);
  }

  handleRetry = () => {
    this.setState(prevState => ({
      hasError: false,
      retryCount: prevState.retryCount + 1,
    }), () => {
      // Ini memaksa komponen untuk me-render ulang. Pertimbangkan pola yang lebih baik dengan props yang terkontrol.
      this.forceUpdate(); // PERINGATAN: Gunakan dengan hati-hati
      if (this.props.onRetry) {
          this.props.onRetry();
      }
    });
  };

  render() {
    if (this.state.hasError) {
      return (
        <div>
          <h2>Terjadi kesalahan.</h2>
          <button onClick={this.handleRetry}>Coba Lagi</button>
        </div>
      );
    }

    return this.props.children;
  }
}

export default ErrorBoundaryWithRetry;

Komponen ErrorBoundaryWithRetry menyertakan tombol coba ulang yang, saat diklik, mengatur ulang state hasError dan me-render ulang komponen turunan. Anda juga dapat menambahkan retryCount untuk membatasi jumlah percobaan ulang. Pendekatan ini bisa sangat berguna untuk menangani kesalahan sementara, seperti gangguan jaringan sementara. Pastikan prop `onRetry` ditangani dengan sesuai dan mengambil ulang/menjalankan ulang logika yang mungkin telah mengalami kesalahan.

2. Feature Flags

Feature flags memungkinkan Anda untuk mengaktifkan atau menonaktifkan fitur di aplikasi Anda secara dinamis, tanpa menerapkan kode baru. Error Boundaries dapat digunakan bersama dengan feature flags untuk menurunkan fungsionalitas secara anggun jika terjadi kesalahan. Misalnya, jika fitur tertentu menyebabkan kesalahan, Anda dapat menonaktifkannya menggunakan feature flag dan menampilkan pesan kepada pengguna yang menunjukkan bahwa fitur tersebut untuk sementara tidak tersedia.

3. Pola Circuit Breaker

Pola circuit breaker adalah pola desain perangkat lunak yang digunakan untuk mencegah aplikasi mencoba berulang kali menjalankan operasi yang kemungkinan besar akan gagal. Ini bekerja dengan memantau tingkat keberhasilan dan kegagalan suatu operasi dan, jika tingkat kegagalan melebihi ambang batas tertentu, "membuka sirkuit" dan mencegah upaya lebih lanjut untuk menjalankan operasi selama periode waktu tertentu. Ini dapat membantu mencegah kegagalan beruntun dan meningkatkan stabilitas aplikasi secara keseluruhan.

Error Boundaries dapat digunakan untuk mengimplementasikan pola circuit breaker dalam aplikasi React. Ketika Error Boundary menangkap kesalahan, ia dapat menambah penghitung kegagalan. Jika penghitung kegagalan melebihi ambang batas, Error Boundary dapat menampilkan pesan kepada pengguna yang menunjukkan bahwa fitur tersebut untuk sementara tidak tersedia dan mencegah upaya lebih lanjut untuk menjalankan operasi. Setelah periode waktu tertentu, Error Boundary dapat "menutup sirkuit" dan mengizinkan upaya untuk menjalankan operasi lagi.

Kesimpulan

React Error Boundaries adalah alat penting untuk membangun aplikasi yang kuat dan ramah pengguna. Dengan mengimplementasikan Error Boundaries, Anda dapat mencegah kesalahan merusak seluruh aplikasi Anda, menyediakan UI fallback yang anggun bagi pengguna Anda, dan mencatat kesalahan ke layanan pemantauan untuk debugging dan analisis. Dengan mengikuti praktik terbaik dan strategi tingkat lanjut yang diuraikan dalam panduan ini, Anda dapat membangun aplikasi React yang tangguh, andal, dan memberikan pengalaman pengguna yang positif, bahkan saat menghadapi kesalahan yang tidak terduga. Ingatlah untuk fokus pada penyediaan pesan kesalahan yang membantu dan dilokalkan untuk audiens global.