liveBook · Manning

Race condition

As explained in React Hooks in Action: With Suspense and Concurrent Mode

A race condition is a correctness problem in which the result depends on the timing or ordering of concurrent operations.

A race condition is a correctness problem where concurrent operations produce results based on timing or ordering. In a bookings UI, an older response can arrive after a newer selection and overwrite the display. section 7.4.5

BookingsGrid response handling

When the selected bookable or week changes, useEffect starts another request. Mark each effect invocation current, update state only while it remains current, and return cleanup that invalidates it: `let doUpdate = true; ... if (doUpdate) setBookings(...); ... return () => doUpdate = false;`. section 7.4.5

Listing 7.13 The BookingsGrid component: 2. Effects
export default function BookingsGrid (
  {week, bookable, booking, setBooking}
) {
  // 1. Variables
 
  useEffect(() => {
    if (bookable) {
      let doUpdate = true;                              #1
 
      setBookings(null);
      setError(false);
      setBooking(null);
 
      getBookings(bookable.id, week.start, week.end)    #2
        .then(resp => {
          if (doUpdate) {                               #3
            setBookings(transformBookings(resp));       #4
          }
        })
        .catch(setError);
 
      return () => doUpdate = false;                    #5
    }
  }, [week, bookable, setBooking]);                     #6
 
  // 3. UI helper
  // 4. UI
}
#1 Use a variable to track whether the bookings data is current.
#2 Call our getBookings data-fetching function.
#3 Check if the bookings data is current.
#4 Create a bookings lookup and assign it to state.
#5 Return a cleanup function to invalidate the data.
#6 Run the effect when the bookable or week changes.

Shows the complete effect lifecycle: request initiation, current-response checking, cleanup, and dependencies. section 7.4.5

Prevent race conditions in effects by:

  • Returning cleanup before rerunning an effect or unmounting. section 4.4
  • Defining async functions inside useEffect rather than making the effect callback async. section 4.2.4

How React Hooks in Action: With Suspense and Concurrent Mode covers it

How deep it goes
Explains timing, effect cleanup, response invalidation, and async-await placement, but defers cancelling in-flight requests.
Examples
Uses the BookingsGrid, getBookings requests, rapidly changed selections, and a doUpdate cleanup flag.
What it assumes
Assumes familiarity with React components, useEffect, promises, state updates, and dependency arrays.
What you can do after
Diagnose stale fetch results and prevent them with useEffect cleanup or correctly nested async functions.
How it connects
Connects useEffect, asynchronous programming, promises, dependencies, and cleanup functions.

Also explained in

Compare how 20 books explain race condition →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of React Hooks in Action: With Suspense and Concurrent Mode. The section links point to the parts of the book it draws on.