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.
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.
Error Boundary to komponent klasowy, który implementuje jedną lub obie z tych metod:
static getDerivedStateFromError(error) - Aktualizuje stan, aby następny render pokazal zastepczy UIcomponentDidCatch(error, errorInfo) - Loguje informację o bledzie (np. do serwisu monitoringu)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}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!Możesz użyć różnych poziomow granularnosci:
1function App() {
2 return (
3 <ErrorBoundary fallback={<h1>Awaria całej stacji!</h1>}>
4 <SpaceStation />
5 </ErrorBoundary>
6 );
7}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}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}Ważne jest wiedziec, że Error Boundaries nie przechwytują błędów w:
try/catchsetTimeout, fetch, Promise1// 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}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>