Skip to content

Concurrent execution of multiple useLazyLoadQuery() may lead to runtime errors due to missing dataΒ #5131

@Yelmuf

Description

@Yelmuf

Hello! πŸ‘‹

This is either I am doing something wrong, or there is an issue that I believe is serious enough to be raised.

Context

We heavily use Relay in our app that contains lots of screens, sub-screens, and independent components that have their own useLazyLoadQuery() in them. And it might happen that several components would fetch different slices of the same GQL record. I am aware of the main Relay guidance that there should be only 1 query per page, and everything else should be a component with its own fragment, but production reality is always something different. :/

Consider this example: list of entities (TODOs) + detail view of an entity (TODO). These two components are independent by routes, but have an overlap in data.
React.StrictMode, of course, and a very aggressive Relay Store option gcReleaseBufferSize: 0 (for showcase purposes).

Normally on a MBP M2 things happen so fast that mostly there are no errors. But various TypeErrors reported in Sentry made us investigate. So I found some conditions in which Relay environment does not behave predictively from my point of view (or I don't understand something).

In a fetchFn for RelayEnvironment if there is a fictional delay placed more than Β±400ms, opening a page with both list and detail view would sometimes end up in list view throwing an error because of missing data.
If bigger delays are set up, and - most importantly - different for different queries, then the list view always resolves in error because useLazyLoadQuery() of list view gets a re-render notification, but store does not return data for the entire list this time, only for a record which has its detail view open:

Screen.Recording.2026-01-07.at.13.24.55.mov

There is an excessive logging of everything what is happening, and right before re-rendering Relay logger reports missing_expected_data.log for most of the stuff in the list:

Image

Question

Is this behavior expected? Or maybe there is something that I'm missing in the setup? Bumping gcReleaseBufferSize to some higher numbers (30-100) does not help.

Resources

I've tried to include most of the stuff we have in production (such as useSyncExternalStore in the middle for storing current detail view ID, or the exact implementation of missingFieldHandlers) yet keep those parts minimal.

Link to repo with reproduction and a test that simulates the above.

Link to Codesandbox.

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