DeployU
Interviews / Frontend Engineering / This statically generated page is showing stale data. How do you fetch and display live data on the client?

Questions

This statically generated page is showing stale data. How do you fetch and display live data on the client?

practical SSG & Data Fetching Interactive Quiz Code Examples

A team is using Static Site Generation (SSG) for their blog to ensure the pages are fast and scalable. The blog post content is generated at build time.

They want to add a “Live Viewers” count to each post. This number should be fresh, client-side data. A junior developer was tasked with this, but the viewer count is always a stale number that was generated at build time; it never updates to a live count.

You’ve been given the BlogPost component. It receives postData as a prop, which represents the data that was fetched and rendered into static HTML at build time.

Your task is to fix the component so that it fetches the live viewer count from a (mock) API when the page loads on the client, and updates the UI to show the fresh data.

BlogPost - Fetch Live Data on SSG Page
Your Code
import React, { useState, useEffect } from 'react';

// Mock API to get the live viewer count
const getLiveViewerCount = (postId) => {
  console.log(`Fetching live count for post ${postId}...`);
  return new Promise(resolve => {
    setTimeout(() => {
      const liveCount = Math.floor(Math.random() * 1000) + 50;
      resolve(liveCount);
    }, 1200);
  });
};

// This component receives data generated at build time.
function BlogPost({ postData }) {
  // The bug: The component only uses the stale `viewers` prop.
  // It never fetches the live data from the client.
  const [post, setPost] = useState(postData);

  return (
    <div>
      <h1>{post.title}</h1>
      <p>{post.content}</p>
      <hr />
      <p>Live Viewers: {post.viewers}</p>
    </div>
  );
}

// To simulate the SSG environment, we'll define the static data
// that would have been generated at build time.
export default function App() {
  const staticData = {
    id: 1,
    title: 'My Fast SSG Blog Post',
    content: 'This content was generated at build time for maximum speed!',
    viewers: 10, // This is the stale viewer count from the build
  };
  return <BlogPost postData={staticData} />;
}
// Validate the fix
const code = document.querySelector('[data-editor]').textContent;

// Check that useEffect is used to fetch data
if (!code.match(/BlogPost[\s\S]*?useEffect/)) {
  throw new Error('Test failed: Use useEffect in BlogPost to fetch live data on the client.');
}

// Check that getLiveViewerCount is called
if (!code.match(/useEffect[\s\S]*?getLiveViewerCount/)) {
  throw new Error('Test failed: Call getLiveViewerCount inside useEffect to fetch the live viewer count.');
}

// Check that state is updated with live data
if (!code.match(/useEffect[\s\S]*?setPost/)) {
  throw new Error('Test failed: Update the post state with the live viewer count inside useEffect.');
}

// Success!
console.log('✓ All tests passed! SSG page now fetches live client-side data.');
console.log('✓ The viewer count will update after the API call completes.');
Click "Run Code" to see output...
Click "Run Code" to see test results...
How Different Experience Levels Approach This
Junior Engineer
Surface Level

I would switch from SSG to SSR (Server-Side Rendering) so that the data is always fresh on each request.

Senior Engineer
Production Ready

I would keep SSG for the main content (fast initial load) but use `useEffect` with an empty dependency array to fetch the live viewer count on the client after the page loads. This hybrid approach gives us the best of both worlds: instant static content delivery with dynamic, client-side data updates for parts that need to be fresh.

The issue here is a misunderstanding of how Static Site Generation (SSG) works with dynamic data. The entire page, including the viewers: 10 data, is pre-rendered into a static HTML file at build time. This makes the initial load incredibly fast.

However, because it’s static, that viewer count will be stale forever until the site is rebuilt.

To display live, dynamic data on a static page, you must fetch it from the client-side after the initial page load. The perfect tool for this is the useEffect hook. By adding a useEffect that runs once on component mount ([]), we can call our API, get the fresh data, and update the component’s state, which triggers a re-render to show the live viewer count.

This approach gives you the best of both worlds: a super-fast initial page load from the static HTML, supplemented by dynamic, live data fetched on the client.

Here is the corrected implementation:

import React, { useState, useEffect } from 'react';

const getLiveViewerCount = (postId) => {
  console.log(`Fetching live count for post ${postId}...`);
  return new Promise(resolve => {
    setTimeout(() => {
      const liveCount = Math.floor(Math.random() * 1000) + 50;
      resolve(liveCount);
    }, 1200);
  });
};

function BlogPost({ postData }) {
  const [post, setPost] = useState(postData);

  // FIX: Fetch live data on the client after the static page loads.
  useEffect(() => {
    getLiveViewerCount(post.id).then(liveCount => {
      // Update the state with the new viewer count
      setPost(currentPost => ({ ...currentPost, viewers: liveCount }));
    });
  }, [post.id]); // Depend on post.id to re-fetch if the post changes

  return (
    <div>
      <h1>{post.title}</h1>
      <p>{post.content}</p>
      <hr />
      <p>Live Viewers: {post.viewers}</p>
    </div>
  );
}

export default function App() {
  const staticData = {
    id: 1,
    title: 'My Fast SSG Blog Post',
    content: 'This content was generated at build time for maximum speed!',
    viewers: 10,
  };
  return <BlogPost postData={staticData} />;
}
What Makes the Difference?
  • Context over facts: Explains when and why, not just what
  • Real examples: Provides specific use cases from production experience
  • Trade-offs: Acknowledges pros, cons, and decision factors

Practice Question

When would you choose Static Site Generation (SSG) over Server-Side Rendering (SSR)?