Skip to content

Error and Suspense handling tooling gap #5032

@tobias-tengler

Description

@tobias-tengler

TL;DR How to verify Error / Suspense boundary (and @catch) coverage at compile time to enforce error and loading state handling?


We've been rolling out @throwOnFieldError at my company and we've run into some challenges I'd like to get feedback on.

Let's consider a page with two sections.

  • The initial view port: We haven't wrapped this part in an Error or Suspense boundary, since we want Errors in this part to kill the page and let suspending content bubble up to block router transitions if data isn't ready yet.
  • Below the initial viewport: This is secondary content and we're working with Suspense and Error Boundaries to provide proper fallbacks in case of data still loading or an error occurring.

Now let's say I have a component in the second section with a @throwOnFieldError fragment. If the component errors it is caught by the ErrorBoundary and everything is well.
If some developer now integrates this component in the initial viewport or anywhere where there isn't an ErrorBoundary, an error in this component will take down the entire page 😱 (we've learned this the hard way unfortunately)

Before we were statically forced by TypeScript to handle null or error cases on a component level. (Note: we can still do this by utilizing @catch, but we also want to have the benefits of UI composition that Error and Suspense boundaries bring)

Error and Suspense boundaries require a whole picture of the application and not just the component you're changing though and there are no safeguards. If you forget to check if there is an Error or Suspense boundary it's game over... Depending on your engineering culture this can be really hard to reconcile with the way that developers work.

I feel like there is a tooling gap with the new data APIs Relay and React are pushing. When I'm integrating a new component I want to know if the error and loading states of that component are handled as expected. Right now it's up to the developer to verify or it to be caught in code-review. This is not resilient, nor effective!

We've been experimenting with some approaches like wrapping our ErrorBoundaries with a Context in development and augmenting useFragment to check if it's within an ErrorBoundary, otherwise it errors. If you want the error to bubble you have to explicitly define this behavior on the useFragment call.
This requires you to actually run the app in development mode though. Otherwise the missing ErrorBoundary won't be surfaced.
Another approach we're currently trying out is static analysis of our component trees by walking ASTs, but this is rather difficult with all of the ways JSX can be passed around. (We haven't even started to look at how we could determine @catch coverage...)

I can't imagine that other companies don't face similar struggles and we'd be very interested to hear how your tackling these issues.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions