Usamos cookies para mejorar tu experiencia en el sitio
CodeWorlds

Zaawansowane wzorce Error Handling

W tej lekcji poznamy zaawansowane techniki obsługi błędów, które możesz zastosowac w złożonych aplikacjach React. Te wzorce są jak zaawansowane systemy bezpieczenstwa na stacji kosmicznej - wielowarstwowe, inteligentne i elastyczne.

Error Monitoring i Logging

W produkcji musisz wiedziec o błędach natychmiast. Zintegruj Error Boundary z systemem monitoringu:

1class MonitoredErrorBoundary extends React.Component {
2  constructor(props) {
3    super(props);
4    this.state = { hasError: false, error: null, errorId: null };
5  }
6
7  static getDerivedStateFromError(error) {
8    return { hasError: true, error };
9  }
10
11  componentDidCatch(error, errorInfo) {
12    // Generuj unikalny ID błędu
13    const errorId = Date.now().toString(36);
14    this.setState({ errorId });
15
16    // Wyslij do serwisu monitoringu
17    logErrorToService({
18      errorId,
19      message: error.message,
20      stack: error.stack,
21      componentStack: errorInfo.componentStack,
22      timestamp: new Date().toISOString(),
23      url: window.location.href,
24      userAgent: navigator.userAgent
25    });
26  }
27
28  render() {
29    if (this.state.hasError) {
30      return (
31        <div className="error-report">
32          <h3>Wystąpił błąd</h3>
33          <p>Kod bledu: {this.state.errorId}</p>
34          <p>Nasz zespol zostal powiadomiony.</p>
35          <button onClick={() => this.setState({ hasError: false })}>
36            Sprobuj ponownie
37          </button>
38        </div>
39      );
40    }
41    return this.props.children;
42  }
43}

Context-aware Error Handling

Różne części aplikacji mogą wymagać roznej obsługi błędów:

1import { createContext, useContext } from 'react';
2
3const ErrorContext = createContext({
4  onError: (error) => console.error(error),
5  severity: 'normal'
6});
7
8function useErrorHandler() {
9  const { onError, severity } = useContext(ErrorContext);
10
11  return (error) => {
12    if (severity === 'critical') {
13      // Dla krytycznych sekcji - wyslij alert
14      sendAlert(error);
15    }
16    onError(error);
17  };
18}
19
20// Uzycie
21function CriticalSection({ children }) {
22  return (
23    <ErrorContext.Provider value={{
24      onError: (err) => sendToMonitoring(err),
25      severity: 'critical'
26    }}>
27      <ErrorBoundary>
28        {children}
29      </ErrorBoundary>
30    </ErrorContext.Provider>
31  );
32}

Error Recovery Strategies

Strategy 1: Automatyczne odświeżanie komponentu

1function AutoRecoveryBoundary({ children, maxRetries = 3 }) {
2  const [retryCount, setRetryCount] = useState(0);
3  const [key, setKey] = useState(0);
4
5  const handleReset = () => {
6    if (retryCount < maxRetries) {
7      setRetryCount(prev => prev + 1);
8      setKey(prev => prev + 1); // Wymusza remount
9    }
10  };
11
12  return (
13    <ErrorBoundary
14      key={key}
15      FallbackComponent={({ error }) => (
16        <div>
17          <p>Błąd: {error.message}</p>
18          {retryCount < maxRetries ? (
19            <button onClick={handleReset}>
20              Sprobuj ponownie ({maxRetries - retryCount} prob pozostalo)
21            </button>
22          ) : (
23            <p>Nie udalo sie naprawic bledu. Skontaktuj sie z supportem.</p>
24          )}
25        </div>
26      )}
27    >
28      {children}
29    </ErrorBoundary>
30  );
31}

Strategy 2: Fallback do prostszej wersji

1function ChartWithFallback({ data }) {
2  return (
3    <ErrorBoundary
4      FallbackComponent={() => (
5        // Zamiast interaktywnego wykresu, pokaz prostą tabele
6        <table>
7          <thead><tr><th>Nazwa</th><th>Wartosc</th></tr></thead>
8          <tbody>
9            {data.map(item => (
10              <tr key={item.id}>
11                <td>{item.name}</td>
12                <td>{item.value}</td>
13              </tr>
14            ))}
15          </tbody>
16        </table>
17      )}
18    >
19      <InteractiveChart data={data} />
20    </ErrorBoundary>
21  );
22}

Global Error Handling

Przechwytuj nieobsluzone błędy na poziomie globalnym:

1// W głównym pliku aplikacji
2useEffect(() => {
3  const handleUnhandledError = (event) => {
4    console.error('Unhandled error:', event.error);
5    // Wyslij do monitoringu
6  };
7
8  const handleUnhandledRejection = (event) => {
9    console.error('Unhandled promise rejection:', event.reason);
10    // Wyslij do monitoringu
11  };
12
13  window.addEventListener('error', handleUnhandledError);
14  window.addEventListener('unhandledrejection', handleUnhandledRejection);
15
16  return () => {
17    window.removeEventListener('error', handleUnhandledError);
18    window.removeEventListener('unhandledrejection', handleUnhandledRejection);
19  };
20}, []);

Podsumowanie wzorcow

| Wzorzec | Kiedy używać | |---------|-------------| | Error Boundary | Błędy renderowania komponentów | | try/catch | Event handlery i kod synchroniczny | | useErrorBoundary | Błędy asynchroniczne w Error Boundary | | Retry | Niestabilne połączenia sieciowe | | Fallback content | Opcjonalne dane | | Global handler | Nieprzewidziane błędy |

Ir a CodeWorlds