Skip to content

Consider adopting tanstack query to replace manual data-fetching boilerplate #1764

@gnugomez

Description

@gnugomez

Our current data-fetching pattern has several maintainability issues:

  • Verbose and abused useEffect blocks — every component that needs data from ExtensionRegistryService must manually convert Promises into state variables (isLoading, error, data). This leads to useEffect being overused as a general-purpose async mechanism. The result is components that are hard to read, hard to test, and prone to side-effect bugs.
  • Manual cancellationAbortController signals need to be manually threaded through each call, which is fragile and difficult to debug when something goes wrong.
  • Unsafe retry behaviorfetch-retry wraps all requests including write mutations, which get silently retried up to 10 times on failure. This is dangerous for non-idempotent operations and invisible to the user.
  • No path to reliable testing — because data-fetching is tightly coupled to the ExtensionRegistryService with no provider abstraction, there is no clean way to mock network behavior in unit or integration tests. TanStack Query's QueryClientProvider is the industry standard solution to this: in production the app uses a real client, and in tests you swap it for a mock one, enabling both hook-level and full component tree testing without any real network calls.

Proposed solution

Adopt TanStack Query (@tanstack/react-query) as the standard data-fetching layer. It handles loading/error state, caching, request deduplication, automatic cancellation, and retry logic out of the box — with sensible defaults (reads retry, mutations do not).

As a future improvement, we could consider leveraging React Error Boundaries alongside TanStack Query's, which lets fetch failures propagate as render errors and be caught at a boundary rather than handled per-component. This opens the door to consistent, centralized error UI without any additional per-hook wiring.

I've created a POC replacing the search query with that #1763

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions