#How to provide a global TanStack Query QueryClientProvider in the New Frontend System

1 messages · Page 1 of 1 (latest)

narrow hazel
#

Hi Backstage community,

I'm migrating our Backstage app to the New Frontend System on Backstage v1.44.2.

In our current (legacy) setup, we use TanStack Query and wrap the entire app with a single QueryClientProvider, so that the same QueryClient is shared across the whole app (plugins + pages):

<QueryClientProvider client={queryClient}>
  <AlertDisplay />
  <OAuthRequestDialog />
  <AppRouter>
    <Root>{routes}</Root>
  </AppRouter>
  <ReactQueryDevtools initialIsOpen={false} />
</QueryClientProvider>

With the New Frontend System, the app is created like this:

const app = createApp({
  features: [convertedOptionsModule, ...convertedRootFeatures],
});

Since we no longer control a single top-level React tree, we’re not sure how to provide a global QueryClientProvider anymore.

Questions:
• What is the recommended way to integrate TanStack Query in the New Frontend System?
• Is there an official or supported pattern to add a global React provider (similar to a top-level wrapper)?
• Should this be implemented via a specific feature or extension point?
• Are there any examples (official or community) for adding shared providers such as TanStack Query or Apollo Client in the new system?

Our goal is to keep one shared QueryClient across the entire app (plugins + pages), and ideally still enable TanStack Query Devtools in development.

Thanks in advance for any guidance!

slim rampart
#

Hi, I just did this change in our Backstage instance. Here is what I did (I don't know if it is the recommended way).
I created this module: react-query-module.tsx:

import { AppRootWrapperBlueprint, createFrontendModule } from '@backstage/frontend-plugin-api';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { ReactQueryDevtools } from '@tanstack/react-query-devtools';

const queryClient = new QueryClient();

const queryClientProviderExtension = AppRootWrapperBlueprint.make({
  name: 'query-client-provider',
  params: {
    component: ({ children }: { children: React.ReactNode }) => (
      <QueryClientProvider client={queryClient}>
        {children}
        <ReactQueryDevtools initialIsOpen={true} />
      </QueryClientProvider>
    ),
  },
});

export const reactQueryClientWrapperModule = createFrontendModule({
  pluginId: 'app',
  extensions: [queryClientProviderExtension],
});

Then I hooked it up in the App.tsx file like this:

import { reactQueryClientWrapperModule } from './modules/react-query.module';

...

const app = createApp({
  features: [
    .... more modules
    reactQueryClientWrapperModule,
    ...convertedRootFeatures,
  ],

I need to do some more testing on this setup, but it seems to work as a "global" enabling of React Query.