Blog>
Snippets

Optimizing Data Fetching with React Server Components

Demonstrate the optimal way of fetching and caching data in React Server Components to minimize data transfer and improve performance.
import { useState, useEffect } from 'react';

export default function DataFetcher({ resource }) {
  const [data, setData] = useState(null);

  useEffect(() => {
    let cancelled = false;

    async function fetchData() {
      const response = await resource.read();
      if (!cancelled) {
        setData(response);
      }
    }

    fetchData();

    return () => {
      cancelled = true;
    };
  }, [resource]);

  if (data === null) {
    throw new Error('Data is not yet available');
  }

  return (
    // Render your component with fetched data
  );
}
This is a hook-like component that fetches data from a passed resource prop and sets it to local state, making sure to avoid state updates if the component unmounts before the data fetching is completed to prevent memory leaks. It throws an error when data is not yet available, relying on error boundaries to handle loading states or fallback UI.
// CacheFactory.js
export default class CacheFactory {
  constructor() {
    this.cache = new Map();
  }

  get(key) {
    return this.cache.get(key);
  }

  set(key, value) {
    this.cache.set(key, value);
  }

  // Call this to clear cache for instance when user logs out
  clear() {
    this.cache.clear();
  }
}
CacheFactory is a simple cache implementation using a JavaScript Map to store and retrieve data. It includes methods to get, set, and clear cache entries. This can be used to cache server data to avoid refetching.
// useServerData.js
import CacheFactory from './CacheFactory';

const cache = new CacheFactory();

export function useServerData(fetcher, key) {
  const cachedData = cache.get(key);

  if (cachedData) {
    return cachedData;
  }

  throw fetcher().then(data => {
    cache.set(key, data);
    return data;
  });
}
useServerData is a custom hook that uses the CacheFactory to check if there is already cached data for a given key and returns it to prevent unnecessary network requests. If the data is not in the cache, it will execute the fetcher function, cache the result, and then return it.
// ReactComponent.server.js
import { useServerData } from './useServerData';

// Simulate fetch function
async function fetchData() {
  // Replace with your actual data fetching code
}

function ReactComponent() {
  const data = useServerData(fetchData, 'unique-cache-key');

  // React component logic using the fetched data
}
In a React Server Component file, we use the custom hook useServerData to obtain data, either from cache or fetch it if necessary. Replace fetchData with actual data fetching logic and ensure that 'unique-cache-key' is unique for each different fetch.