TanStack / query

🤖 Powerful asynchronous state management, server-state utilities and data fetching for the web. TS/JS, React Query, Solid Query, Svelte Query and Vue Query.
https://tanstack.com/query
MIT License
41.84k stars 2.84k forks source link

Doesn't work out of the box with next 13 #4933

Closed JonasWijne closed 1 year ago

JonasWijne commented 1 year ago

Describe the bug

when adding react-query to next 13 i get following error when running

error - ./node_modules/@tanstack/react-query/build/lib/Hydrate.mjs
Attempted import error: 'useRef' is not exported from 'react' (imported as 'React').

Import trace for requested module:
./node_modules/@tanstack/react-query/build/lib/Hydrate.mjs
./node_modules/@tanstack/react-query/build/lib/index.mjs
./src/app/layout.tsx

code

import {QueryClient, QueryClientProvider} from "@tanstack/react-query";

const queryClient = new QueryClient()

/* ... */
      <QueryClientProvider client={queryClient}>
          {children}
      </QueryClientProvider>
/* ... */

Your minimal, reproducible example

https://github.com/JonasWijne/next-test-react-query

Steps to reproduce

  1. git clone https://github.com/JonasWijne/next-test-react-query.git
  2. cd next-test-react-query
  3. yarn
  4. yarn dev
  5. open browser to http://localhost:3000

Expected behavior

as a user i expect it to compile/dev serve

How often does this bug happen?

Every time

Screenshots or Videos

image

Platform

TanStack Query version

4.24.4

TypeScript version

4.9.5

Additional context

No response

Bknight010723 commented 1 year ago

sdkmanager --uninstall --package_file #4939

d4nyll commented 1 year ago

With Next.js 13's app directory feature, every component, by default, is a Server Component. Which means you are trying to use context in a Server Component, which is not supported. Instead, you should create a new Client Component (with 'use client'; directive), apply your context provider there (alongside any other context providers), and import that in your root layout.

'use client';

import { QueryClient, QueryClientProvider } from 'react-query'

const queryClient = new QueryClient()

export default function QueryProvider({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <QueryClientProvider client={queryClient}>
      {children}
    </QueryClientProvider>
  );
}

export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html lang="en">
      {/*
        <head /> will contain the components returned by the nearest parent
        head.tsx. Find out more at https://beta.nextjs.org/docs/api-reference/file-conventions/head
      */}
      <head />
      <body>
        <QueryProvider>
          {children}
        </QueryProvider>
      </body>
    </html>
  )
}

See Using context in Client Components for more details.

OrmEmbaar commented 1 year ago

I am seeing the same error. The TanStack docs suggest creating a singleton client on the server for import into server components, but that does not seem to work.

I do not get the error with the initialData approach outlined in the docs, presumably because it does not create a client on the server. I am using Next 13.1.6 and react-query 4.24.4.

arzzzen commented 1 year ago

+1 have the same error after attempt to follow TanStack docs

barbarah commented 1 year ago

I also cannot get it working with Hydrate, following the docs. It does work with the initialData.

I made a sandbox with a very simple Next 13 app. I made two examples, one with initial data, and one with hydrate, by following the TanStack docs for Next 13. The hydrate code throws the error.

https://codesandbox.io/p/sandbox/next13-react-query-h4qh77

TkDodo commented 1 year ago

The docs say you have to put the providers into a separate app/providers.tsx file that has 'use client' at the top. I did that and it works, here's a fork of your reproduction:

https://codesandbox.io/p/sandbox/gracious-merkle-8lzrrk

Talent30 commented 1 year ago

The docs say you have to put the providers into a separate app/providers.tsx file that has 'use client' at the top. I did that and it works, here's a fork of your reproduction:

https://codesandbox.io/p/sandbox/gracious-merkle-8lzrrk

Yes, it works up to now but once you start using getQueryClient in server component you get the error error - ../../node_modules/@tanstack/react-query/build/lib/Hydrate.mjs Attempted import error: 'useRef' is not exported from 'react' (imported as 'React').

Talent30 commented 1 year ago

@TkDodo demo

TkDodo commented 1 year ago

@Ephem do you know why this is happening? It seems like

import { QueryClient } from "@tanstack/react-query"; brings in a lot more than just the QueryClient, as the error comes form Hydrate.tsx. Removing that import makes it work. However, Hydrate.tsx alone has the 'use client' directive at the top 🤔

Talent30 commented 1 year ago

@TkDodo If you go to the Hydrate.esm.js output the 'use client' is not there for some reason, has it been removed during the build process? I am using v4.24.4.

Talent30 commented 1 year ago

Can't upload img...

module path: node_modules/@tanstack/react-query/build/lib/Hydrate.esm.js

line 1: import * as React from 'react';

source code path: react-query/src/Hydrate.tsx line 1: 'use client' line 2: import * as React from 'react'

TkDodo commented 1 year ago

I think it could be this:

probably we'd need to preserve the directive for esm builds?

Talent30 commented 1 year ago

I think it could be this:

probably we'd need to preserve the directive for esm builds?

The way suggested will add 'use client' to every single file isn't it? Would it be harmful?

TkDodo commented 1 year ago

The way suggested will add 'use client' to every single file isn't it? Would it be harmful?

We have added use client to every file that needs it. When bundled together into one file, it should be removed, which is what rollup does. But for ESM builds, I think separate files are being kept, so we probably would need the use client directive there.

I'm gonna wait for some input from @Ephem if that's correct or not.

Ephem commented 1 year ago

Busy days so will look at this in more detail soon, but I think you've definitely found the cause. Will need to think a bit on how this affects the different builds, can we even have a single entry point when with builds that bundle into a single file?

I think we ran into this during the docs-PR as well so at some point we recommended importing what you can from import { QueryClient } from '@tanstack/query-core' instead of import { QueryClient } from '@tanstack/react-query' which might still be a working workaround/fix.

TkDodo commented 1 year ago

importing what you can from import { QueryClient } from '@tanstack/query-core'

but for this, eslint will likely force you to have a direct dependency on query-core, which most people won't have. Also, if you add query-core as a dependency, you will wind up with two version of query-core, because react-query re-exports the core. Difficult topic 😅

pixelmord commented 1 year ago

I ran into the same error

Attempted import error: 'useRef' is not exported from 'react' (imported as 'React').

Import trace for requested module:
../../node_modules/.pnpm/@tanstack+react-query@4.24.6_biqbaboplfbrettd7655fr4n2y/node_modules/@tanstack/react-query/build/lib/Hydrate.mjs

To fix that I wrapped all components that imported from '@tanstack/react-query' in components that "use client" and imported all functions used in server components from '@tanstack/query-core' e.g.

import { QueryClient, dehydrate } from '@tanstack/query-core';
satnaing commented 1 year ago

I also cannot get it working with Hydrate, following the docs. It does work with the initialData.

I made a sandbox with a very simple Next 13 app. I made two examples, one with initial data, and one with hydrate, by following the TanStack docs for Next 13. The hydrate code throws the error.

https://codesandbox.io/p/sandbox/silly-poincare-w6q5nk

@barbarah Have you already solved that problem?

I'm facing the same issue. I cannot prefetch data on server using Hydrate method. initialData along with prop drilling works though. I'm doing the exact same thing according to docs

barbarah commented 1 year ago

Sorry, no. I've tried the different options mentioned above. But I did not get my sandbox working.

I did update the sandbox link because apparently, the link was not working: https://codesandbox.io/p/sandbox/next13-react-query-h4qh77

feledori commented 1 year ago

I got it working by doing these step:

  1. Wrapping the Hydrate wrapper in a separate "use client" component
  2. Importing QueryClient from @tanstack/query-core in the server singleton
  3. Importing the dehydrate function from @tanstack/query-core as well.

@barbarah Here is the working sandbox with the changes I just mentioned.

mk965 commented 1 year ago

I got it working by doing these step:

  1. Wrapping the Hydrate wrapper in a separate "use client" component
  2. Importing QueryClient from @tanstack/query-core in the server singleton
  3. Importing the dehydrate function from @tanstack/query-core as well.

@barbarah Here is the working sandbox with the changes I just mentioned.

@feledori

Good job! But in your demo "getPost" is run twice. Once on the server, once on the client.

feledori commented 1 year ago

@mk965 Just updated the sandbox, you just have to disable revalidateOnMount for the hydrated useQuery hook.

Ephem commented 1 year ago

I finally did some digging and thinking on this today and thought I'd document my findings:

I think we should:

Ephem commented 1 year ago

Actually, what we could do now as a temporary fix is add "use client" to the top of the entire react-query package with the Rollup banner2-plugin as documented in that issue (maybe only for the .mjs build?) and just document that on the server you have to use @tanstack/query-core for now? As long as you always use that only in RSCs, and always import from @tanstack/react-query elsewhere we shouldn't have a problem with duplicates right?

Ephem commented 1 year ago

I got nerdsniped and built a Rollup plugin to preserve directives: https://github.com/Ephem/rollup-plugin-preserve-directives

I'll do some more testing, but with this I think we should be able to make it all work as per the docs.

TkDodo commented 1 year ago

please try it with:

mahdi-farnia commented 1 year ago

I did every thing including Provider file that has 'use client' directive and everything i found, But it didn't work

Does this occurs because of next 13.3.0? (provided examples in this thread are using version 13.1.x)

2manoj1 commented 1 year ago

Hello Everyone! I made small POC with Next13 and React Query - Its working. Have a look Example code

Need a feedback or suggestion if any

momenfc commented 1 year ago

try to import dehydrate from '@tanstack/query-core' instead '@tanstack/react-query' import { dehydrate } from '@tanstack/query-core';

Schmale97 commented 1 year ago

I did every thing including Provider file that has 'use client' directive and everything i found, But it didn't work

Does this occurs because of next 13.3.0? (provided examples in this thread are using version 13.1.x)

I have also been able to get it to work with next version >=13.3.0 and @tanstack/* version 4.29.12

Nishchit14 commented 7 months ago

I just found the fix, In my case I was using one valtio function in utils.ts file which was used somewhere in the server side api.

Rule is if you're using any client side library then make sure that you're not using it's client apis/functions of library directly or indirectly on server routes or server actions.

Franklivania commented 5 months ago

I got it working by doing these step:

1. Wrapping the Hydrate wrapper in a separate "use client" component

2. Importing QueryClient from @tanstack/query-core in the server singleton

3. Importing the dehydrate function from @tanstack/query-core as well.

@barbarah Here is the working sandbox with the changes I just mentioned.

This worked, and this is an outline of what I am using

"@tanstack/react-query": "^4.29.7",
    "next": "13.5.6",