We use cookies to enhance your experience on the site
CodeWorlds

Main Project: Resilient Space Dashboard

Time to combine all the techniques we've learned into one project! You'll create an error-resilient space dashboard that demonstrates Error Boundaries, Suspense, skeleton loaders, graceful degradation, and retry patterns.

Project Requirements

Your dashboard should include:

  1. Application-level Error Boundary - catches critical errors
  2. Section-level Error Boundaries - isolate module failures
  3. Suspense with skeleton loaders - elegant component loading
  4. Retry mechanism - ability to retry after an error
  5. Graceful degradation - partial failures don't destroy the entire application

Project Architecture

1// Resilient Space Dashboard Structure
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>

Key Elements to Implement

1. Reusable Error Boundary with Retry

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 || 'Module failure'}</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}

2. Skeleton Loader for Sections

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}

3. Component with Error Simulation

1function UnstableModule({ failRate = 0.3 }) {
2  const [data, setData] = useState(null);
3
4  useEffect(() => {
5    // Simulate an unstable 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>Initializing...</p>;
16  return (
17    <div className="module-status">
18      <span>Status: {data.status}</span>
19      <span>Power: {data.power}%</span>
20    </div>
21  );
22}

4. Graceful Degradation -- Partial Functionality

When one module fails, the rest of the dashboard should work normally:

1function FallbackPanel({ title, onRetry }) {
2  return (
3    <div className="fallback-panel">
4      <h3>{title} - Offline</h3>
5      <p>This module is temporarily unavailable.</p>
6      <p>Other systems are operating normally.</p>
7      <button onClick={onRetry}>Retry</button>
8    </div>
9  );
10}

5. Retry with Attempt Limit

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('Retry limit exceeded'));
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}

Implementation Tips

  • Use
    class ErrorBoundary extends React.Component
    for custom Error Boundaries
  • Give each module its own Error Boundary -- a failure in one should not destroy the entire dashboard
  • Add a "Restart module" button in the fallback UI of each Error Boundary
  • Create reusable skeleton loaders matching each section
  • Combine Error Boundary + Suspense for dynamically loaded components
  • Add cosmic styling -- dark background, neon accents, space station theme

Evaluation Criteria

  1. Application-level Error Boundary -- catches critical errors
  2. At least 3 sections with separate Error Boundaries -- each can "break" independently
  3. Suspense used with at least one lazy-loaded component
  4. Skeleton loader -- visible during loading
  5. Retry button -- ability to retry after an error
  6. Graceful degradation -- the rest of the dashboard works despite one section's failure

Review the editor below with the example implementation and modify it according to your needs!

Go to CodeWorlds