A data-access function retrieves asynchronous data while presenting one callable interface for three outcomes: it throws a pending promise, throws an error, or returns loaded data. React components can call it during rendering so Suspense handles loading and an error boundary handles failure. section 12.1.2 section 12.4
Build and use the pattern in these steps:
- Start the request early, often outside the component, and pass the resulting function into the component when scope or user interaction requires it. section 12.1.3
- Wrap a promise with makeThrower; inspect its status, throw the promise while pending, throw the error on failure, and return the result after success. section 12.1.2
- Store a data-access function in state with useState(() => function) and update it with setState(() => function), because passing the function directly makes React invoke it as an updater. section 12.1.4
- Let Suspense render its loading fallback and let an error boundary provide recovery UI; treat the pattern as experimental rather than production-ready. section 12.1.3 section 12.4
Loading the next message
Create getFirstMessage with makeThrower(fetchMessage()), store it in App state, and pass it to Message. When the user clicks Next, fetch the next message, wrap its promise in a new throwing function, and store that function. Message calls getMessage(); pending work displays “Loading message...”, while the resolved result displays “Bonjour”. section 12.1.4
Listing 12.3 Returning a data-fetching function that throws as appropriate
export function makeThrower (promiseIn) { #1
const checkStatus = getStatusChecker(promiseIn); #2
return function () { #3
const {promise, status, result} = checkStatus(); #4
if (status === "pending") throw promise; #5
if (status === "error") throw result; #5
return result; #5
};
}
Inspect the compact makeThrower implementation that converts promise status into Suspense-compatible throws or returned data. section 12.1.2
Listing 7.10 The getBookings API function
import {shortISO} from "./date-wrangler"; #1
export function getBookings (bookableId, startDate, endDate) { #2
const start = shortISO(startDate); #3
const end = shortISO(endDate); #3
const urlRoot = "http://localhost:3001/bookings";
const query = `bookableId=${bookableId}` + #4
`&date_gte=${start}&date_lte=${end}`; #4
return getData(`${urlRoot}?${query}`); #5
}
#1 Import a function to format dates.
#2 Export the new getBookings function.
#3 Format the dates for the query string.
#4 Build up the query string.
#5 Fetch the bookings, returning a promise.
Compare the message-specific pattern with getBookings, a parameterized data-access function that builds a query and returns a promise. section 7.4.3
