Not handling network errors in fetch/axios

Loading

Proper Network Error Handling in React Applications

Handling network errors properly is crucial for creating robust React applications. Here’s how to implement comprehensive error handling for fetch and Axios requests.

Fetch API Error Handling

Basic Error Handling

// ❌ Bad - no error handling
fetch('/api/data')
  .then(response => response.json())
  .then(data => setData(data));

Proper Implementation

// ✅ Good - complete error handling
async function fetchData() {
  try {
    const response = await fetch('/api/data');

    if (!response.ok) { // Handle HTTP errors (404, 500, etc.)
      throw new Error(`HTTP error! status: ${response.status}`);
    }

    const data = await response.json();
    setData(data);
  } catch (error) {
    console.error('Fetch error:', error);
    setError(error.message);
    // Optionally show user notification
    notifyUser('Failed to load data. Please try again.');
  }
}

Axios Error Handling

Basic Error Handling

// ❌ Bad - minimal error handling
axios.get('/api/data')
  .then(response => setData(response.data));

Proper Implementation

// ✅ Good - comprehensive error handling
async function fetchData() {
  try {
    const response = await axios.get('/api/data', {
      timeout: 5000, // Set timeout
      headers: { 'Authorization': `Bearer ${token}` }
    });
    setData(response.data);
  } catch (error) {
    if (axios.isAxiosError(error)) {
      // Axios-specific error
      if (error.response) {
        // Server responded with non-2xx status
        console.error('Server error:', error.response.status);
        setError(`Server error: ${error.response.status}`);
      } else if (error.request) {
        // Request made but no response
        console.error('Network error:', error.message);
        setError('Network error - please check your connection');
      } else {
        // Something else happened
        console.error('Request setup error:', error.message);
        setError('Failed to send request');
      }
    } else {
      // Non-Axios error
      console.error('Unexpected error:', error);
      setError('An unexpected error occurred');
    }
  }
}

Advanced Error Handling Patterns

1. Centralized Error Handler

// errorHandler.js
export function handleNetworkError(error) {
  if (error.response) {
    switch (error.response.status) {
      case 401:
        return 'Please login to continue';
      case 403:
        return 'You don\'t have permission';
      case 404:
        return 'Resource not found';
      case 500:
        return 'Server error - please try later';
      default:
        return `Error: ${error.response.status}`;
    }
  } else if (error.request) {
    return 'Network error - please check your connection';
  } else {
    return 'An unexpected error occurred';
  }
}

// In your component
try {
  await axios.get('/api/data');
} catch (error) {
  setError(handleNetworkError(error));
}

2. Retry Mechanism

async function fetchWithRetry(url, retries = 3) {
  try {
    const response = await fetch(url);
    if (!response.ok) throw new Error(response.statusText);
    return await response.json();
  } catch (error) {
    if (retries <= 0) throw error;
    await new Promise(resolve => setTimeout(resolve, 1000));
    return fetchWithRetry(url, retries - 1);
  }
}

// Usage
fetchWithRetry('/api/data')
  .then(data => setData(data))
  .catch(error => setError(error.message));

3. Error Boundary Integration

class ErrorBoundary extends React.Component {
  state = { hasError: false };

  static getDerivedStateFromError(error) {
    return { hasError: true };
  }

  componentDidCatch(error, info) {
    logErrorToService(error, info.componentStack);
  }

  render() {
    if (this.state.hasError) {
      return <FallbackUI />;
    }
    return this.props.children;
  }
}

// Wrap components that make network requests
<ErrorBoundary>
  <DataFetchingComponent />
</ErrorBoundary>

Best Practices

  1. Always handle both network and HTTP errors (failed requests and 4xx/5xx responses)
  2. Provide user-friendly messages – don’t show raw error objects
  3. Implement loading states – show spinners during requests
  4. Consider retries for transient failures (network blips, 502 errors)
  5. Log errors to your monitoring service
  6. Set timeouts to prevent hanging requests
  7. Cancel requests when components unmount (using AbortController)

Common Mistakes to Avoid

  1. Only catching network errors but ignoring HTTP error statuses
  2. Silently failing without user feedback
  3. Not cleaning up requests when components unmount
  4. Assuming all errors are the same without proper classification
  5. Not implementing loading states leaving users guessing

Leave a Reply

Your email address will not be published. Required fields are marked *