Utilizziamo i cookie per migliorare la tua esperienza sul sito
CodeWorlds

Error Boundaries - straze twojej aplikacji

Error Boundaries (granice błędów) to specjalne komponenty React, które działają jak systemy bezpieczenstwa na stacji kosmicznej. Gdy jeden moduł ulegnie awarii, Error Boundary izoluje problem i zapobiega zniszczeniu całej stacji.

Czym są Error Boundaries?

Error Boundary to komponent klasowy React, który przechwytuje błędy JavaScript w całym drzewie komponentów potomnych, loguje je i wyświetla zastepczy UI zamiast drzewa, które uleglo awarii.

Dwie kluczowe metody

Error Boundary to komponent klasowy, który implementuje jedną lub obie z tych metod:

  1. static getDerivedStateFromError(error)
    - Aktualizuje stan, aby następny render pokazal zastepczy UI
  2. componentDidCatch(error, errorInfo)
    - Loguje informację o bledzie (np. do serwisu monitoringu)

Podstawowa implementacja

1import React from 'react';
2
3class ErrorBoundary extends React.Component {
4  constructor(props) {
5    super(props);
6    this.state = { hasError: false, error: null };
7  }
8
9  // Wywoływana gdy komponent potomny rzuci błąd
10  // Zwraca obiekt aktualizujący stan
11  static getDerivedStateFromError(error) {
12    return { hasError: true, error: error };
13  }
14
15  // Wywoływana po przechwyceniu błędu
16  // Swietne miejsce na logowanie błędów
17  componentDidCatch(error, errorInfo) {
18    console.error('Error caught:', error);
19    console.error('Component stack:', errorInfo.componentStack);
20  }
21
22  render() {
23    if (this.state.hasError) {
24      return (
25        <div className="error-fallback">
26          <h2>Cos poszlo nie tak!</h2>
27          <p>{this.state.error?.message}</p>
28        </div>
29      );
30    }
31
32    return this.props.children;
33  }
34}

Uzywanie Error Boundaries

Error Boundary opakowuje komponenty, które chcemy chronic:

1function SpaceStation() {
2  return (
3    <div className="station">
4      <ErrorBoundary>
5        <Navigation />
6      </ErrorBoundary>
7
8      <ErrorBoundary>
9        <MainPanel />
10      </ErrorBoundary>
11
12      <ErrorBoundary>
13        <StatusBar />
14      </ErrorBoundary>
15    </div>
16  );
17}

Teraz jeśli

MainPanel
rzuci błąd,
Navigation
i
StatusBar
dalej będą działac!

Granularnosc Error Boundaries

Możesz użyć różnych poziomow granularnosci:

Poziom aplikacji (ogólna siatka bezpieczenstwa)

1function App() {
2  return (
3    <ErrorBoundary fallback={<h1>Awaria całej stacji!</h1>}>
4      <SpaceStation />
5    </ErrorBoundary>
6  );
7}

Poziom sekcji (izolacja modułów)

1function SpaceStation() {
2  return (
3    <div>
4      <ErrorBoundary fallback={<p>Nawigacja offline</p>}>
5        <Navigation />
6      </ErrorBoundary>
7      <ErrorBoundary fallback={<p>Panel sterowania niedostepny</p>}>
8        <ControlPanel />
9      </ErrorBoundary>
10    </div>
11  );
12}

Poziom komponentu (precyzyjna izolacja)

1function Dashboard() {
2  return (
3    <div className="dashboard">
4      {widgets.map(widget => (
5        <ErrorBoundary key={widget.id} fallback={<WidgetError />}>
6          <Widget data={widget} />
7        </ErrorBoundary>
8      ))}
9    </div>
10  );
11}

Co Error Boundaries NIE przechwytują

Ważne jest wiedziec, że Error Boundaries nie przechwytują błędów w:

  1. Event handlerach - uzywaj
    try/catch
  2. Kodzie asynchronicznym -
    setTimeout
    ,
    fetch
    , Promise
  3. Renderowaniu po stronie serwera (SSR)
  4. Bledach w samym Error Boundary (a nie w jego dzieciach)
1// Event handler - wymaga try/catch
2function Button() {
3  const handleClick = () => {
4    try {
5      riskyOperation();
6    } catch (err) {
7      // Obsluż błąd tutaj
8    }
9  };
10  return <button onClick={handleClick}>Klik</button>;
11}

Customowy fallback z propem

Najlepsza praktyka to tworzenie reużywalnego Error Boundary z konfigurowalnym fallbackiem:

1class ErrorBoundary extends React.Component {
2  constructor(props) {
3    super(props);
4    this.state = { hasError: false, error: null };
5  }
6
7  static getDerivedStateFromError(error) {
8    return { hasError: true, error };
9  }
10
11  componentDidCatch(error, info) {
12    console.error('Error boundary caught:', error, info);
13  }
14
15  render() {
16    if (this.state.hasError) {
17      // Uzywamy fallback prop jeśli jest dostępny
18      if (this.props.fallback) {
19        return this.props.fallback;
20      }
21      return <h2>Wystąpił błąd</h2>;
22    }
23    return this.props.children;
24  }
25}
26
27// Uzycie z customowym fallbackiem
28<ErrorBoundary fallback={<p>Moduł uszkodzony, ale stacja działa!</p>}>
29  <RiskyModule />
30</ErrorBoundary>
Vai a CodeWorlds