Today, I tackled a common yet crucial frontend challenge: handling loading states when fetching dynamic data in a React app. Without a proper loading indicator, users might stare at a blank screen, wondering if the app is broken—especially when network requests take longer than expected.
Here’s how I gracefully managed this in my Book Tracker app, ensuring a smoother user experience without unnecessary visual disruption.
The Problem: A Sudden Lag in Data Fetching
In my initial setup, the App component rendered the <BookTable /> immediately, even before the data finished loading from readings.json. This meant that for a brief moment, users saw an empty table—or worse, if the fetch failed, they saw no table at all.
Here’s what my return statement originally looked like:
|
1 2 3 4 5 6 7 8 9 10 |
return ( <main> <h1>Book Tracker</h1> <StatusFilter value={statusFilter} onChange={setStatusFilter} /> <BookTable readings={filteredReadings} /> </main> ); |
While this worked once the data loaded, it didn’t communicate what was happening during the fetch. I needed a way to tell the user: “Hold on, your data is on the way.”
The Solution: Adding a Loading State
I introduced a new piece of state to track whether the data was still being fetched:
|
1 2 3 |
const [readings, setReadings] = useState([]); const [statusFilter, setStatusFilter] = useState(“all”); const [loading, setLoading] = useState(true); // ← NEW |
Then, inside useEffect, I made sure to set loading to false once the data arrived—or if an error occurred:
|
1 2 3 4 5 6 7 8 9 10 11 12 |
useEffect(() => { fetch(“/readings.json”) .then((response) => response.json()) .then((data) => { setReadings(data); setLoading(false); }) .catch((error) => { console.error(“Failed to load readings:”, error); setLoading(false); }); }, []); |
Finally, I updated the render logic to conditionally show either a loading message or the main content:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
return ( <main> <h1>Book Tracker</h1> {loading ? ( <p>Loading your reading list ...</p> ) : ( <> <StatusFilter value={statusFilter} onChange={setStatusFilter} /> <BookTable readings={filteredReadings} /> </> )} </main> ); |





Leave a Reply