Optimistic Progress Updates

Introduction: Instant Feedback for Progress Updates

Welcome back! In the previous lesson, you learned how to fetch and display your personalized reading shelf using data from a NestJS API. Now, let’s take the next step: allowing users to update their reading progress and see those changes instantly.

When you update your progress in a book, you want to see the new page number right away, not wait for the server to respond. This is where the concept of Optimistic UI comes in. With Optimistic UI, your app updates the interface immediately, assuming the server will succeed. If something goes wrong, the app can roll back to the previous state.

This approach makes your app feel much faster and more responsive, which is especially important for interactive features like progress tracking.

Shelf and Progress Features

To understand how progress editing fits in, let’s revisit the MyShelfPage component. It renders your shelf entries and, for each book, includes a ProgressEditor. The shelf itself still uses React Query’s useQuery, but now every entry has an input and button that let the user edit their page progress.

src/features/shelf/MyShelfPage.tsx (excerpt)

{data.map((item) => (
  <li key={item.bookId} className="bg-slate-800 p-4 rounded-lg">
    <div className="font-semibold text-sky-400">{item.title}</div>
    <div className="text-slate-400">by {item.author}</div>
    <div className="mt-1 text-sm">
      Page {item.currentPage} • {Math.round(item.progress * 100)}% • {item.status}
    </div>
    <div className="mt-2">
      <ProgressEditor item={item} />
    </div>
  </li>
))}
  • The shelf page is responsible for fetching and rendering data. Each entry shows the title, author, and current stats.
  • ProgressEditor is a new component dedicated to editing progress.
  • Each shelf item passes its data (item) down, so the editor knows which book and what the current page is.
  • The parent page still handles fetching the shelf and rendering each entry in a list.

With this setup, we isolate editing logic from the shelf display logic. The shelf page focuses only on displaying data, while the editor handles the interactions.

The `updateProgress` API

Before looking at the editor, let’s examine the API helper that makes progress updates possible. It’s defined alongside the existing getShelf function.

src/api/reading.ts

export async function updateProgress(body: UpdateProgressPayload) {
  return apiClient.patch("/reading/progress", body);
}
  • This function wraps a PATCH request to the /reading/progress backend route.
  • It expects a body shaped like UpdateProgressPayload, which includes userId, bookId, currentPage, and optionally a status.
  • By centralizing this in the API layer, our components don’t worry about HTTP details or headers.

This small function becomes the foundation of all progress editing features in the UI.

Sign up

Join the 1M+ learners on CodeSignal

Be a part of our community of 1M+ users who develop and demonstrate their skills on CodeSignal