Skip to content

Consuming the react query useQuery hook from third party lib cause error #9129

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
shmdhussain opened this issue May 8, 2025 · 4 comments
Closed

Comments

@shmdhussain
Copy link

shmdhussain commented May 8, 2025

Describe the bug

Note: I read this issue #3595 which is about using the useQuery hook from the third party lib.

In that issue @TkDodo mentioned that if the react and react-query version are same , It will work, when I try that it is not working.

Demo

I created one simple demo stackblitz (https://stackblitz.com/~/github.com/shmdhussain/react-query-third-party-lib) using monorepo.

use npm run start to see the demo works,

Reproduce steps:

just click to comp1 (it works correctly) but when you click comp2 it wont work because of the error No QueryClient set, use QueryClientProvider to set one

explanation of my issue

In the demo, I placed my app @mymonorepo/my-appwhich consumes two libs (@mymonorepo/my-lib-1) and (@mymonorepo/my-lib-2) (consider those two as 3rd party libs giving us custom hooks (useFetchIds' which internally uses the useQuery`).

In @mymonorepo/my-lib-1 I just exported hook only and made the react query as external peer deps to be provided by consuming lib which is @mymonorepo/my-app

In @mymonorepo/my-lib-2 I exported/bundled hook along with the react query, in that case when consuming from my app is not working , when I debugged the bundled code of 3rd part lib found that useQuery from the 3rd party lib uses the context from the 3rd party lib rather than from the consuming app, which causes this issue.

By @TkDodo comment in the issue, If i use same version of react and react-query it should work, but not working. Am I missing anything here or any work around to make it work?

Thanks in advance for any help

Expected behavior

It should work from third party hooks.

How often does this bug happen?

None

Screenshots or Videos

Image

Platform

  • All

Tanstack Query adapter

None

TanStack Query version

5.75.5

TypeScript version

No response

Additional context

No response

@TkDodo
Copy link
Collaborator

TkDodo commented May 9, 2025

I checked out the reproduction locally.

  • in the root, I ran npm install
  • then, I tried npm run start, which doesn’t exist as the root level package.json doesn’t have any scripts
  • I tried to cd into apps/my-app but there too, npm run start doesn’t exist. But, there’s a dev script which runs vite so I tried that but it yielded errors:
  ✘ [ERROR] Failed to resolve entry for package "@mymonorepo/my-lib-1". The package may have incorrect main/module/exports specified in its package.json. [plugin vite:dep-scan]

what I could get to work is to do npm run build in both my-lib-1 and my-lib-2 and then do npm run dev, but that is far from the description that you provided on how to run this thing.

So please update your instructions, I don’t want to play a guessing game if what I’m doing is right as this is usually just a huge waste of my time.

Anyways, if I then do npm run build in the my-app directory and inspect the output, I can see that two react contexts are created:

// line 16508
var QueryClientContext$1 = reactExports.createContext(
  void 0
);
// line 17473
var QueryClientContext = reactExports.createContext(
  void 0
);

That indeed “just” means your bundling process creates and bundles two version of react-query. You can search for all things that end with $1 and you’ll see that you basically have two versions of react-query bundled.

I don’t know how npm monorepos work or what you have to do to resolve this, but you’d get the same result with any library creates a react context if it gets duplicated like that. You would even get the same result if you’d create your own react context in the libs if they get duplicated like that.

So there is nothing we can do on our end here.

@TkDodo TkDodo closed this as not planned Won't fix, can't repro, duplicate, stale May 9, 2025
@shmdhussain
Copy link
Author

shmdhussain commented May 9, 2025

I checked out the reproduction locally.

  • in the root, I ran npm install
  • then, I tried npm run start, which doesn’t exist as the root level package.json doesn’t have any scripts
  • I tried to cd into apps/my-app but there too, npm run start doesn’t exist. But, there’s a dev script which runs vite so I tried that but it yielded errors:
  ✘ [ERROR] Failed to resolve entry for package "@mymonorepo/my-lib-1". The package may have incorrect main/module/exports specified in its package.json. [plugin vite:dep-scan]

what I could get to work is to do npm run build in both my-lib-1 and my-lib-2 and then do npm run dev, but that is far from the description that you provided on how to run this thing.

So please update your instructions, I don’t want to play a guessing game if what I’m doing is right as this is usually just a huge waste of my time.

Anyways, if I then do npm run build in the my-app directory and inspect the output, I can see that two react contexts are created:

// line 16508
var QueryClientContext$1 = reactExports.createContext(
  void 0
);
// line 17473
var QueryClientContext = reactExports.createContext(
  void 0
);

That indeed “just” means your bundling process creates and bundles two version of react-query. You can search for all things that end with $1 and you’ll see that you basically have two versions of react-query bundled.

I don’t know how npm monorepos work or what you have to do to resolve this, but you’d get the same result with any library creates a react context if it gets duplicated like that. You would even get the same result if you’d create your own react context in the libs if they get duplicated like that.

So there is nothing we can do on our end here.

sorry for the confusion in adding steps to reproduce, I thought I committed the code but still it was in stackblitz local, now pushed to github and demo works. click comp1 and comp2 links to see the issue

as @TkDodo said what happens is two different contexts are created and bundled , one from the third party lib and another from the consuming app.

The third party useQuery hook is using the context that is exported with the third party app bundled code to get queryClient.

But when I check the react-query code there is already an option to pass queryClient from the consuming app through useQuery hook

Here I think solution could be is passing the queryClient from the consuming app to the useQuery like useQuery(options, queryClient) (already param there to pass) and then use the passed query client in the react- query code, so I get my app's queryClient

ReactQuery code (with my suggestions commented as suggested)

# react query code
function useQuery(options, queryClient) {
  return useBaseQuery(options, QueryObserver2);
  //suggested here to pass the queryClient to useBaseQuery
  //return useBaseQuery(options, QueryObserver2, queryClient);
}

function useBaseQuery(options, Observer, queryClient) {
  const client = useQueryClient();
  //suggested code in below line, pass queryclient, if there is one
  //const client = useQueryClient(queryClient);

  //other code goes here ...
}

var QueryClientContext = React.createContext(
  void 0
);
var useQueryClient = (queryClient) => {
  /*START: suggested code use queryclient if passed one is there else follow as is*/
  //if(queryClient){
    //return queryClient
  //}
 /*END: suggested code */
  const client = reactExports.useContext(QueryClientContext);
  if (!client) {
    throw new Error("No QueryClient set, use QueryClientProvider to set one");
  }
  return client;
};

My lib code

function useMyhook(queryClient){
  return useQuery(undefined, queryClient)
}

My app

//import {useMyhook} from "thirdparty-lib"


//consuemr react comp
const queryClient = useQueryClient()
useMyhook(queryClient); //passing consumer app queryClient

@TkDodo
Copy link
Collaborator

TkDodo commented May 9, 2025

you can do that but you’re still bundling react-query twice, which you shouldn’t do. I’d rather fix that.

@shmdhussain
Copy link
Author

you can do that but you’re still bundling react-query twice, which you shouldn’t do. I’d rather fix that.

Agreed 10/10 I will do that way only , but that third party lib is legacy code, already exporting lot of usequery hooks and I like to make it work without making the react-query as externals in that lib

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants