Questions
This statically generated page is showing stale data. How do you fetch and display live data on the client?
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.
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} />;
} How Different Experience Levels Approach This
I would switch from SSG to SSR (Server-Side Rendering) so that the data is always fresh on each request.
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} />;
} - 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)?