Editing Shelf Status
Introduction: Why Edit Shelf Status?
Welcome back! In the last lessons, you learned how to fetch your reading shelf and update your reading progress. Now, let’s take the next step: editing the status of a book on your shelf.
Shelf status is a simple way to track where you are with each book. For example, you might want to mark a book as “Want to read,” “In progress,” or “Completed.” This helps you organize your reading and see your progress at a glance.
In this lesson, you will learn how to let users change the status of a book directly from their shelf. This is a key feature for any modern reading app, and it builds on what you’ve already learned about React state and optimistic UI updates.
How the StatusEditor Works
The StatusEditor component is responsible for letting users change the status of a book. It displays a set of buttons, one for each possible status. When you click a button, the status for that book is updated and the change is reflected immediately in the UI.
Here’s the main part of the StatusEditor component:
-
A local
selectedstate tracks the currently highlighted status for immediate visual feedback. -
useMutationis configured withupdateProgress, sending bothcurrentPageand the newstatus. -
onMutateprovides optimistic UI:- Cancels ongoing shelf queries.
- Stores the previous shelf data so we can roll back if needed.
- Updates the cache immediately so the UI reflects the change right away.
- Updates local state with
setSelected(status).
-
onErrorrestores the previous state if something fails. -
onSettledinvalidates the shelf query, ensuring eventual consistency with the backend. -
The
qcvariable is a query client instance provided by React Query. It acts as the gateway to the entire query cache: letting us cancel queries, read cached data (getQueryData), update cached data (setQueryData), and request fresh data (invalidateQueries). Without the query client, optimistic UI would not be possible, because components would only react to server responses instead of cache manipulations. -
In
onMutate, we first callqc.cancelQueriesto stop any in-flight requests that might overwrite our optimistic changes. We then snapshot the current cache (getQueryData) and update it with the new status (setQueryData). This makes the UI respond instantly, before the network request finishes. Finally, we update local component state so the currently selected button is highlighted. -
The
Btnis a locally defined inner component insideStatusEditor. We do this because these buttons are tightly coupled to the logic and state ofStatusEditor. Defining it inline avoids the overhead of a separate file, keeps all relevant code in one place, and makes it easy to reuse the same styles and behavior across multiple status values. Since the button’s only purpose is to render status-specific options and trigger mutations, a standalone component would add unnecessary indirection.
This combination of cache manipulation with the query client (qc) and a local inline Btn definition gives us a fast, responsive, and maintainable way to let users update shelf status in real time. This ensures that a click on a status button feels instant while still being reliable.
