CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-swr

React Hooks library for remote data fetching with stale-while-revalidate caching strategy

Pending
Overview
Eval results
Files

global-configuration.mddocs/

Global Configuration

The SWRConfig component provides global configuration for all SWR hooks within its scope, enabling centralized management of fetchers, error handling, and other options.

Capabilities

SWRConfig Component

Provider component for configuring SWR behavior globally across the application.

/**
 * Provider component for global SWR configuration
 * @param props.value - Partial configuration object to apply globally
 * @param props.children - Child components that will inherit the configuration
 */
interface SWRConfig {
  (props: {
    value?: Partial<SWRConfiguration>;
    children: React.ReactNode;
  }): JSX.Element;
  
  /** Default configuration values */
  defaultValue: SWRConfiguration;
}

Usage Examples:

import { SWRConfig } from "swr";

// Basic global configuration
function App() {
  return (
    <SWRConfig 
      value={{
        fetcher: (url: string) => fetch(url).then(res => res.json()),
        onError: (error) => {
          console.error('SWR Error:', error);
        }
      }}
    >
      <MyComponents />
    </SWRConfig>
  );
}

// Advanced configuration with multiple options
function App() {
  return (
    <SWRConfig 
      value={{
        fetcher: customFetcher,
        revalidateOnFocus: false,
        revalidateOnReconnect: true,
        errorRetryCount: 3,
        errorRetryInterval: 1000,
        onError: handleGlobalError,
        onSuccess: handleGlobalSuccess,
        shouldRetryOnError: (error) => error.status >= 500,
      }}
    >
      <Router />
    </SWRConfig>
  );
}

useSWRConfig Hook

Hook to access the current SWR configuration and global mutate function.

/**
 * Hook to access current SWR configuration and global utilities
 * @returns Object containing cache, mutate function, and current configuration
 */
function useSWRConfig(): {
  cache: Cache;
  mutate: (key?: Key, data?: any, options?: boolean | MutatorOptions) => Promise<any>;
  [key: string]: any;
};

Usage Examples:

import { useSWRConfig } from "swr";

function MyComponent() {
  const { mutate, cache } = useSWRConfig();
  
  // Global cache mutation
  const handleInvalidateAll = () => {
    mutate(() => true); // Revalidate all keys
  };
  
  // Specific cache mutation
  const handleUpdateUser = (newUser: User) => {
    mutate(`/api/users/${newUser.id}`, newUser, false);
  };
  
  // Cache inspection (for debugging)
  const handleLogCache = () => {
    console.log("Current cache:", cache);
  };
  
  return (
    <div>
      <button onClick={handleInvalidateAll}>Refresh All Data</button>
      <button onClick={handleLogCache}>Log Cache</button>
    </div>
  );
}

Nested Configuration

SWR configurations can be nested, with inner configurations overriding outer ones.

function App() {
  return (
    <SWRConfig 
      value={{
        fetcher: globalFetcher,
        revalidateOnFocus: false,
      }}
    >
      <Header />
      
      {/* Admin section with different configuration */}
      <SWRConfig 
        value={{
          fetcher: adminFetcher, // Overrides global fetcher
          revalidateOnFocus: true, // Overrides global setting
          onError: adminErrorHandler,
        }}
      >
        <AdminPanel />
      </SWRConfig>
      
      <MainContent />
    </SWRConfig>
  );
}

Global Error Handling

Configure global error handling for all SWR hooks.

function App() {
  return (
    <SWRConfig
      value={{
        onError: (error, key) => {
          // Global error logging
          console.error(`Error for key ${key}:`, error);
          
          // Report to error tracking service
          errorTracker.captureException(error, { extra: { key } });
          
          // Show user-friendly error messages
          if (error.status === 401) {
            // Redirect to login
            window.location.href = "/login";
          } else if (error.status >= 500) {
            toast.error("Server error. Please try again later.");
          } else if (error.status === 404) {
            toast.error("Resource not found.");
          }
        },
        
        onErrorRetry: (error, key, config, revalidate, { retryCount }) => {
          // Don't retry on 404
          if (error.status === 404) return;
          
          // Don't retry on authentication errors  
          if (error.status === 401) return;
          
          // Only retry up to 3 times
          if (retryCount >= 3) return;
          
          // Exponential backoff
          setTimeout(() => revalidate({ retryCount }), 2 ** retryCount * 1000);
        }
      }}
    >
      <App />
    </SWRConfig>
  );
}

Global Success Handling

Configure global success callbacks for all SWR hooks.

function App() {
  return (
    <SWRConfig
      value={{
        onSuccess: (data, key) => {
          // Global success logging
          console.log(`Successfully loaded ${key}`);
          
          // Analytics tracking
          analytics.track("data_loaded", { key });
          
          // Cache warming for related data
          if (key.includes("/api/user/")) {
            // Pre-load user's related data
            const userId = key.split("/").pop();
            mutate(`/api/user/${userId}/preferences`);
          }
        }
      }}
    >
      <App />
    </SWRConfig>
  );
}

Global Fetcher Configuration

Set up a global fetcher with authentication, error handling, and request configuration.

// Global fetcher with authentication and error handling
const globalFetcher = async (url: string) => {
  const token = getAuthToken();
  
  const response = await fetch(url, {
    headers: {
      "Content-Type": "application/json",
      ...(token && { Authorization: `Bearer ${token}` }),
    },
  });
  
  if (!response.ok) {
    const error = new Error(`HTTP ${response.status}: ${response.statusText}`);
    (error as any).status = response.status;
    (error as any).response = response;
    throw error;
  }
  
  return response.json();
};

function App() {
  return (
    <SWRConfig value={{ fetcher: globalFetcher }}>
      <Router />
    </SWRConfig>
  );
}

// Advanced fetcher with request interceptors
const advancedFetcher = async (url: string | [string, RequestInit]) => {
  const [actualUrl, options = {}] = Array.isArray(url) ? url : [url, {}];
  
  // Add default headers
  const headers = {
    "Content-Type": "application/json",
    ...options.headers,
  };
  
  // Add authentication
  const token = getAuthToken();
  if (token) {
    headers.Authorization = `Bearer ${token}`;
  }
  
  // Make request
  const response = await fetch(actualUrl, {
    ...options,
    headers,
  });
  
  // Handle different response types
  const contentType = response.headers.get("content-type");
  
  if (!response.ok) {
    let errorMessage = `HTTP ${response.status}: ${response.statusText}`;
    
    // Try to get more specific error from response body
    try {
      if (contentType?.includes("application/json")) {
        const errorData = await response.json();
        errorMessage = errorData.message || errorMessage;
      }
    } catch {}
    
    const error = new Error(errorMessage);
    (error as any).status = response.status;
    throw error;
  }
  
  // Return appropriate data format
  if (contentType?.includes("application/json")) {
    return response.json();
  } else if (contentType?.includes("text/")) {
    return response.text();
  } else {
    return response.blob();
  }
};

Performance Configuration

Configure SWR for optimal performance based on your application needs.

function App() {
  return (
    <SWRConfig
      value={{
        // Reduce revalidation frequency for better performance
        dedupingInterval: 5000, // 5 seconds
        focusThrottleInterval: 10000, // 10 seconds
        
        // Disable revalidation for better perceived performance
        revalidateOnFocus: false,
        revalidateOnReconnect: true,
        
        // Optimize error retry
        errorRetryCount: 2,
        errorRetryInterval: 2000,
        shouldRetryOnError: (error) => {
          // Only retry on network errors and 5xx responses
          return !error.status || error.status >= 500;
        },
        
        // Keep data fresh but reduce network requests
        refreshInterval: 60000, // 1 minute polling for critical data
        refreshWhenHidden: false,
        refreshWhenOffline: false,
        
        // Improve loading experience
        keepPreviousData: true,
        loadingTimeout: 3000,
        
        onLoadingSlow: (key) => {
          console.warn(`Slow loading detected for: ${key}`);
          // Could show a loading indicator or warning
        }
      }}
    >
      <App />
    </SWRConfig>
  );
}

Environment-Specific Configuration

Configure SWR differently based on environment.

const getConfig = () => {
  const baseConfig = {
    fetcher: globalFetcher,
  };
  
  if (process.env.NODE_ENV === "development") {
    return {
      ...baseConfig,
      // More aggressive revalidation in development
      revalidateOnFocus: true,
      revalidateOnReconnect: true,
      // Shorter intervals for testing
      dedupingInterval: 1000,
      errorRetryInterval: 500,
      // Detailed logging
      onError: (error, key) => {
        console.group(`SWR Error: ${key}`);
        console.error(error);
        console.groupEnd();
      },
      onSuccess: (data, key) => {
        console.log(`SWR Success: ${key}`, data);
      }
    };
  }
  
  if (process.env.NODE_ENV === "production") {
    return {
      ...baseConfig,
      // Conservative revalidation in production
      revalidateOnFocus: false,
      revalidateOnReconnect: true,
      // Longer intervals for better performance
      dedupingInterval: 10000,
      errorRetryInterval: 5000,
      // Error reporting only
      onError: (error, key) => {
        errorReporter.captureException(error, { extra: { key } });
      }
    };
  }
  
  return baseConfig;
};

function App() {
  return (
    <SWRConfig value={getConfig()}>
      <Router />
    </SWRConfig>
  );
}

Dynamic Configuration

Update SWR configuration based on application state.

function ConfigurableApp() {
  const [isOnline, setIsOnline] = useState(navigator.onLine);
  const [userPreferences, setUserPreferences] = useState(null);
  
  useEffect(() => {
    const handleOnline = () => setIsOnline(true);
    const handleOffline = () => setIsOnline(false);
    
    window.addEventListener("online", handleOnline);
    window.addEventListener("offline", handleOffline);
    
    return () => {
      window.removeEventListener("online", handleOnline);
      window.removeEventListener("offline", handleOffline);
    };
  }, []);
  
  const swrConfig = useMemo(() => ({
    fetcher: globalFetcher,
    
    // Adjust behavior based on connection
    revalidateOnReconnect: isOnline,
    refreshWhenOffline: false,
    errorRetryCount: isOnline ? 3 : 0,
    
    // Adjust based on user preferences
    revalidateOnFocus: userPreferences?.autoRefresh ?? true,
    refreshInterval: userPreferences?.pollInterval ?? 0,
    
    // Custom pause logic
    isPaused: () => {
      // Pause requests when offline or user disabled auto-refresh
      return !isOnline || userPreferences?.pauseRequests;
    }
  }), [isOnline, userPreferences]);
  
  return (
    <SWRConfig value={swrConfig}>
      <App />
    </SWRConfig>
  );
}

Install with Tessl CLI

npx tessl i tessl/npm-swr

docs

cache-management.md

core-data-fetching.md

global-configuration.md

immutable-data.md

index.md

infinite-loading.md

mutations.md

subscriptions.md

tile.json