Skip to content
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

getBlitzContext() can only be used in React Server Components in Nextjs 13 or higher #4242

Closed
molysulfur opened this issue Oct 30, 2023 · 11 comments · Fixed by #4299
Closed
Labels
kind/bug Something isn't working status/done

Comments

@molysulfur
Copy link

molysulfur commented Oct 30, 2023

What is the problem?

when i use next13 i found problem in "invoke function"

i get error "getBlitzContext() can only be used in React Server Components in Nextjs 13 or higher"

in Page.ts
`
import { gSSP, invoke } from "src/blitz-server"

export const getServerSideProps = gSSP(async ({ ctx }) => {
const data = await invoke(..., null)
return { props: { data } }
})

`

in blitz-server.ts
export const { gSSP, gSP, api, invoke } = setupBlitzServer({ plugins: [ AuthServerPlugin({ ...authConfig, storage: PrismaStorage(db), isAuthorized: simpleRolesIsAuthorized, }), RpcServerPlugin({}) ], logger: BlitzLogger({}) });

how i can fix?

@molysulfur molysulfur added kind/bug Something isn't working status/triage labels Oct 30, 2023
@siddhsuresh
Copy link
Member

Thanks for the issue, this has been fixed in the latest release
@molysulfur upgrade to latest blitz beta 35, and update the import you are using to

-import { gSSP, invoke } from "src/blitz-server"
+import {gSSP} from "src/blitz-server"
+import {invoke} from "@blitzjs/rpc"

I am closing the issue since this issue has already been fixed. If it is still present in the latest version, please inform and update the issue. Thanks!

@akboolz
Copy link

akboolz commented Oct 31, 2023

I get this error in new version when i use const user = await invoke(getCurrentUser, {}) in page.tsx.

Internal error: Error: getBlitzContext() can only be used in React Server Components in Nextjs 13 or higher
web-dash:dev: at \node_modules.pnpm@[email protected][email protected][email protected]\node_modules@blitzjs\auth\dist\chunks\auth-plugin.cjs:165:13

@tordans
Copy link
Contributor

tordans commented Oct 31, 2023

@akboolz Had the same problem after updating to .35 but using the fix to import invoke like import {invoke} from "@blitzjs/rpc" solved the issue for me.

tordans added a commit to FixMyBerlin/atlas-app that referenced this issue Oct 31, 2023
@akboolz
Copy link

akboolz commented Oct 31, 2023

@tordans

Well its not the same I think. Because query getCurrentUser depends on blitz Ctx ( so we can get session inside query ).

In blitz docs:
Note we cannot directly import invoke from @blitzjs/rpc due to the necessity to run the required middleware in order to make it work effectively.

So invoke in this case needs to imported from 'blitz-server' not @blitzjs/rpc.
Otherwise session will undefined ( i guess because auth middleware was not applied ):

Query function:

export default async function getCurrentUser(_ = null, { session }: Ctx) {
  if (!session.userId) return null;

  const user = await db.user.findFirst({
    where: { id: session.userId },
    select: { id: true, name: true, email: true, role: true, apiKey: true },
  });

  return user;
}

Error if importing invoke from "@blitzjs/rpc"

TypeError: Cannot destructure property 'session' of 'undefined' as it is undefined.
web-dash:dev:     at getCurrentUser (../../web-apis/dash-api/user/queries/getCurrentUser.ts:8:73

My sample code in page.tsx in app folder ( the idea is to get authed user on server ) where I get error "getBlitzContext() can only be used in React Server Components in Nextjs 13 or higher"

import { useAuthenticatedBlitzContext, invoke } from '../blitz-lib/blitz-server'
import { DashboardLayout } from '../components/dashboard/DashboardLayout'
import getCurrentUser from 'dash-api/user/queries/getCurrentUser'

const DashboardPage = async () => {
  await useAuthenticatedBlitzContext({
    redirectTo: '/auth/login',
  })

  const user = await invoke(getCurrentUser, {})

  return (
    <DashboardLayout
      pageTitle="Dashboard"
      dasboardHeader="Dashboard"
      user={user}
    />)
}

The strange thing is that it works on first load but after changing code / page refresh / link click, this error can show up randomly.

@tordans
Copy link
Contributor

tordans commented Oct 31, 2023

@akboolz that would be a question for @siddhsuresh. Or maybe a new ticket to give the Ctx part more visibility.

@siddhsuresh
Copy link
Member

@akboolz to be more clear, all usages of invoke in the app directory only in React Server components should be from app/blitz-server (wherever the file is) and in all pages directory and in Client Components use the import from @blitzjs/rpc

Hope this solves your issue.

@tordans
Copy link
Contributor

tordans commented Nov 9, 2023

@siddhsuresh we upgraded our app (app directory) from beta .34 to beta .35 and we now have the same issue with the missing session when getCurrentUser, which requires a session/Ctx.

Please reopen this issue.

Update: There is a test case app for this error in #4243 (comment)

@siddhsuresh siddhsuresh reopened this Nov 28, 2023
@siddhsuresh
Copy link
Member

siddhsuresh commented Nov 28, 2023

@tordans @akboolz This is fixed in beta 36. Let me know if you are still facing issues. Thanks!

@tordans
Copy link
Contributor

tordans commented Nov 28, 2023

@siddhsuresh thanks for looking into this and reopening the issue!

@tordans @akboolz This is fixed in beta 36. Let me know if you are still facing issues. Thanks!

First test case:

I am getting

Unhandled Runtime Error
Error: getBlitzContext() can only be used in React Server Components in Nextjs 13 or higher

image

For the page http://127.0.0.1:5173/regionen which loads this file https://github.com/FixMyBerlin/atlas-app/blob/develop/src/app/regionen/(index)/page.tsx (a RSC) which imports two RSC:

  1. one with an invoke and a unsuspecting getter https://github.com/FixMyBerlin/atlas-app/blob/develop/src/app/regionen/(index)/_components/RegionListPublic.tsx
  2. one with an invoke and a getCurrentUser which I suspect is the issue https://github.com/FixMyBerlin/atlas-app/blob/develop/src/app/regionen/(index)/_components/RegionListNonpublic.tsx

Second test case:

I updated the test app for #4243 (comment) and the error cases described in that commend are still same.

For this ticket the last error is relevant at http://localhost:3000/projects-session-error/foo

Unhandled Runtime Error
Error: Cannot read properties of undefined (reading 'session')"

This is a server component using invoke from @blitzjs/rpc and getProjectSessionError has the regular resolver.authorize().


Third test case:

Update: This test case was wrong. Following the docs https://blitzjs.com/docs/usage-next-13#app-directory for how to get ctx and user does work.

@siddhsuresh
Copy link
Member

siddhsuresh commented Nov 28, 2023

@tordans thanks for the very detailed explanation.
Now, looking at the code shared, you would need to revert the import of invoke to app/blitz-server.

Importing invoke from @blitzjs/rpc would only work well, if you are in calling it from a client component or from the pages directory.

Now regarding the getBlitzContext error that happens in case 1. Can you clear the .next/, node_modules and try. In my latest test from a fresh new app, the fix implemented looked to solve the problem.

If this is not the case, will try replicating the issue by cloning your repo, since this looks to be severe

@tordans
Copy link
Contributor

tordans commented Nov 30, 2023

@siddhsuresh I am getting super confused by this error. It is there on one day and gone the next 😞.

I am removing /.next and /node_modules before each test to have a clean test setup, but still the results change from day to day.

The error I see, when I see it (in both the test app and our real app), is …

Error: getBlitzContext() can only be used in React Server Components in Nextjs 13 or higher
    at /Users/foo/blitz-test-app-directory-error/node_modules/@blitzjs/auth/dist/chunks/auth-plugin.cjs:165:13
    at processTicksAndRejections (node:internal/process/task_queues:95:5)
    at runNextTicks (node:internal/process/task_queues:64:3)
    at listOnTimeout (node:internal/timers:533:9)
    at process.processTimers (node:internal/timers:507:7)

I will try again next week…

I can say that the behavior is different between dev and production env.

In case someone want to add data points, here is my test setup:

(And a similar test for https://github.com/FixMyBerlin/atlas-app/blob/develop/src/app/regionen/(index)/_components/RegionListNonpublic.tsx)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
kind/bug Something isn't working status/done
Projects
Status: Done
5 participants