blitz-js / blitz

⚡️ The Missing Fullstack Toolkit for Next.js

Home Page:https://Blitzjs.com

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

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

molysulfur opened this issue · comments

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?

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!

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@blitzjs+auth@2.0.0-beta.35_blitz@2.0.0-beta.35_next@13.5.4\node_modules@blitzjs\auth\dist\chunks\auth-plugin.cjs:165:13

@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

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.

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

@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.

@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)

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

@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.

@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

@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)