Czas połączyc wszystkie poznane techniki w jednym projekcie! Stworzysz odporny na błędy kosmiczny dashboard, który demonstruje Error Boundaries, Suspense, skeleton loadery, graceful degradation i wzorce retry.
Twoj dashboard powinien zawierac:
1// Struktura Resilient Space Dashboard
2<AppErrorBoundary>
3 <SpaceDashboard>
4 <Header />
5
6 <ErrorBoundary fallback={<MissionFallback />}>
7 <Suspense fallback={<MissionSkeleton />}>
8 <MissionControl />
9 </Suspense>
10 </ErrorBoundary>
11
12 <ErrorBoundary fallback={<SystemFallback />}>
13 <Suspense fallback={<SystemSkeleton />}>
14 <SystemStatus />
15 </Suspense>
16 </ErrorBoundary>
17
18 <ErrorBoundary fallback={<CrewFallback />}>
19 <CrewPanel />
20 </ErrorBoundary>
21 </SpaceDashboard>
22</AppErrorBoundary>1class RetryErrorBoundary 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 handleRetry = () => {
12 this.setState({ hasError: false, error: null });
13 };
14
15 render() {
16 if (this.state.hasError) {
17 return (
18 <div className="error-panel">
19 <h3>{this.props.title || 'Awaria modulu'}</h3>
20 <p>{this.state.error.message}</p>
21 <button onClick={this.handleRetry}>Restart</button>
22 </div>
23 );
24 }
25 return this.props.children;
26 }
27}1function SectionSkeleton({ lines = 3 }) {
2 return (
3 <div className="section-skeleton">
4 <div className="skeleton-header skeleton-pulse" />
5 {Array.from({ length: lines }).map((_, i) => (
6 <div
7 key={i}
8 className="skeleton-line skeleton-pulse"
9 style={{ width: `${Math.random() * 40 + 60}%` }}
10 />
11 ))}
12 </div>
13 );
14}1function UnstableModule({ failRate = 0.3 }) {
2 const [data, setData] = useState(null);
3
4 useEffect(() => {
5 // Symulacja niestabilnego API
6 const timer = setTimeout(() => {
7 if (Math.random() < failRate) {
8 throw new Error('Module malfunction detected!');
9 }
10 setData({ status: 'operational', power: 98 });
11 }, 1000);
12 return () => clearTimeout(timer);
13 }, []);
14
15 if (!data) return <p>Inicjalizacja...</p>;
16 return (
17 <div className="module-status">
18 <span>Status: {data.status}</span>
19 <span>Moc: {data.power}%</span>
20 </div>
21 );
22}Gdy jeden modul zawiedzie, reszta dashboardu powinna dzialac normalnie:
1function FallbackPanel({ title, onRetry }) {
2 return (
3 <div className="fallback-panel">
4 <h3>{title} - Offline</h3>
5 <p>Ten modul jest tymczasowo niedostepny.</p>
6 <p>Pozostale systemy dzialaja normalnie.</p>
7 <button onClick={onRetry}>Ponow probe</button>
8 </div>
9 );
10}1function useRetry(asyncFn, maxRetries = 3) {
2 const [retryCount, setRetryCount] = useState(0);
3 const [error, setError] = useState(null);
4
5 const retry = async () => {
6 if (retryCount >= maxRetries) {
7 setError(new Error('Przekroczono limit prob'));
8 return;
9 }
10 try {
11 setRetryCount(prev => prev + 1);
12 await asyncFn();
13 setError(null);
14 } catch (err) {
15 setError(err);
16 }
17 };
18
19 return { retry, error, retryCount, canRetry: retryCount < maxRetries };
20}class ErrorBoundary extends React.Component dla własnych Error BoundariesPrzejrzyj poniższy edytor z przykładową implementacją i zmodyfikuj ją wedlug swoich potrzeb!