When an API request fails, show an explicit error state rather than leaving the affected part of your React app blank. Keep loading and failure states distinct, and offer a retry when a fresh request could recover. The right implementation depends on how data is loaded: an ordinary fetch in an Effect or event handler needs its own error handling, while errors thrown during rendering belong to an Error Boundary.
Why a blank area is the wrong failure state
A blank panel gives users no clue whether data is still loading, failed to load, or was intentionally omitted. Render a pending state while work is in progress and a separate failure state once the request fails. The failure message can identify which content could not be loaded and provide a retry control when retrying makes sense.
As an Amazon Associate I earn from qualifying purchases.
React does not prescribe a universal request-state shape or a particular data-fetching library for this. The important point is to represent request failure in the request flow and render UI from that state.
Handle request failures where the request happens
For fetches in Effects or event handlers
Track whether the request is pending, successful, or failed, and render the corresponding interface. A retry should start a fresh request and update that state so the error message does not remain after recovery.
#1 Best Overall
Do not expect a Suspense boundary to handle an ordinary fetch initiated in an Effect or event handler. React explicitly says Suspense does not detect data fetching performed in those places. Its fallback is for a child that suspends through a supported mechanism, not a universal loading or API-error screen. See React’s Suspense documentation.
For Suspense-enabled data or Promise-reading code
Suspense can show a fallback while a child is waiting, then reveal the child when it is ready. That pending fallback is not itself an error message. If a Promise read with React’s use rejects, the rejection needs an Error Boundary to determine the error UI; a retry pattern can supply a new Promise and reset the boundary. React demonstrates a “Try again” action with a changed boundary key in its documentation for use. Treat that as one supported pattern, not the only retry architecture.
Use an Error Boundary for errors thrown while rendering
An Error Boundary catches eligible errors thrown while React renders descendant components or their hooks. It can replace the part of the tree below it with a fallback interface. A normal try/catch around JSX in a parent does not catch an error thrown later as React renders a child. React’s lint guidance puts it plainly: “Try/catch blocks can’t catch errors that happen during React’s rendering process.” Read the Error Boundaries guidance and the Component reference for boundary behavior and state methods.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Place the boundary at the intended failure scope
The nearest Error Boundary determines the fallback for a rendering error. A boundary around one data panel can preserve the page header, navigation, and neighboring controls; a boundary higher in the tree replaces more of the interface. Choose based on what should remain useful if that subtree fails. There is no single boundary hierarchy that fits every app.
Rank #3
An Error Boundary is not a substitute for request-level error handling. If a fetch rejects in an Effect or handler, put that failure into the request’s state or data-fetching layer and render from it. Use a boundary for eligible rendering errors, or for rejected Promises read through a mechanism that routes them to a boundary.
Make retry restore the failed state cleanly
A retry control should do more than dismiss the message: it should initiate a new attempt. For request-state UI, update the request state as the new attempt begins and then show the result. If an Error Boundary is displaying a rendering failure, the retry path must also reset or remount the failed boundary state; React’s use example uses a changed key to do this for its Promise-reading pattern.
Rank #4
Whether to offer retry is a product decision. It is useful when another attempt could plausibly succeed; the interface should not suggest that retrying is guaranteed to fix the underlying problem.
What changes with streaming server rendering
Streaming server rendering has a distinct recovery path. If a component error is contained beneath Suspense, the server can emit the nearest Suspense fallback in the HTML, then React retries rendering that component on the client. If it fails on the client as well, the nearest Error Boundary controls the visible error UI. Errors in the shell have separate server handling. This behavior is not the same as an API request failing after the application has already loaded. See React’s streaming server rendering reference.
Quick Recap
Best Value
A practical decision checklist
- Is work still pending? Show a loading or Suspense fallback appropriate to the data mechanism.
- Did an ordinary Effect or handler request fail? Store that failure in request state or the data layer and render an explicit error state.
- Did a descendant throw during rendering? Put an Error Boundary above the subtree whose interface should be replaced.
- Can the user recover? Make retry start fresh work, and reset an Error Boundary when the chosen pattern requires it.
- Does the app stream server-rendered HTML? Account for Suspense fallback, client retry, and separate shell-error handling.
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




