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.
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)
@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](https://private-user-images.githubusercontent.com/111561/286376963-ef80cd02-e974-43c8-b29b-e9076ee5edd3.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MDQ2MzYyNTcsIm5iZiI6MTcwNDYzNTk1NywicGF0aCI6Ii8xMTE1NjEvMjg2Mzc2OTYzLWVmODBjZDAyLWU5NzQtNDNjOC1iMjliLWU5MDc2ZWU1ZWRkMy5wbmc_WC1BbXotQWxnb3JpdGhtPUFXUzQtSE1BQy1TSEEyNTYmWC1BbXotQ3JlZGVudGlhbD1BS0lBVkNPRFlMU0E1M1BRSzRaQSUyRjIwMjQwMTA3JTJGdXMtZWFzdC0xJTJGczMlMkZhd3M0X3JlcXVlc3QmWC1BbXotRGF0ZT0yMDI0MDEwN1QxMzU5MTdaJlgtQW16LUV4cGlyZXM9MzAwJlgtQW16LVNpZ25hdHVyZT01NjkyOGRhMzBjYjkyMWZlM2Q2ZjQ2ZjI2ZWQ4ZTUwMmQxNGZkYzY3MDk3YjU5ODQyNTVlYjFmNjZlMzdmNGZkJlgtQW16LVNpZ25lZEhlYWRlcnM9aG9zdCZhY3Rvcl9pZD0wJmtleV9pZD0wJnJlcG9faWQ9MCJ9.H-nH_pHhFuGx-dwRT3rZ5H4JCqtu8OkgVOgtzoqKRQY)
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:
- one with an invoke and a unsuspecting getter https://github.com/FixMyBerlin/atlas-app/blob/develop/src/app/regionen/(index)/_components/RegionListPublic.tsx
- 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:
- https://github.com/FixMyBerlin/blitz-test/blob/main/src/app/get-current-user-ctx/page.tsx
withnpm run bleach && npm run dev
- https://github.com/FixMyBerlin/blitz-test/blob/main/src/app/get-current-user-ctx/page.tsx
withnpm run bleach && npm run build && npm run start
- https://github.com/FixMyBerlin/blitz-test/blob/main/src/app/get-current-user-invoke/page.tsx
withnpm run bleach && npm run dev
- https://github.com/FixMyBerlin/blitz-test/blob/main/src/app/get-current-user-invoke/page.tsx
withnpm run bleach && npm run build && npm run start
(And a similar test for https://github.com/FixMyBerlin/atlas-app/blob/develop/src/app/regionen/(index)/_components/RegionListNonpublic.tsx)