Next.js Discord

Discord Forum

Module not found errors after introducing "use server"

Answered
Mini Rex posted this in #help-forum
Open in Discord
Avatar
Mini RexOP
Hi all, I've just added "use server" to one of my pages; in order to make use of getServerSideProps, and I now my page fails to compile. The following errors are present:
Uncaught Error: Module not found: Can't resolve 'react-server-dom-webpack/client'

https://nextjs.org/docs/messages/module-not-found

Import trace for requested module:
./src/pages/midlands/index.tsx
    at <unknown> (https://nextjs.org/docs/messages/module-not-found)
    at getNotFoundError (file://E:\AdriftDev\adriftdev\node_modules\next\dist\build\webpack\plugins\wellknown-errors-plugin\parseNotFoundError.js:128:16)
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async getModuleBuildError (file://E:\AdriftDev\adriftdev\node_modules\next\dist\build\webpack\plugins\wellknown-errors-plugin\webpackModuleError.js:102:27)
    at async (file://E:\AdriftDev\adriftdev\node_modules\next\dist\build\webpack\plugins\wellknown-errors-plugin\index.js:21:49)
    at async (file://E:\AdriftDev\adriftdev\node_modules\next\dist\build\webpack\plugins\wellknown-errors-plugin\index.js:19:21)

Module not found: Can't resolve '@vercel/turbopack-ecmascript-runtime/dev/client/hmr-client.ts'

https://nextjs.org/docs/messages/module-not-found

Import trace for requested module:
./node_modules/next/dist/client/components/react-dev-overlay/hot-reloader-client.js
./node_modules/next/dist/client/components/app-router.js
./node_modules/next/dist/client/app-call-server.js
./node_modules/next/dist/build/webpack/loaders/next-flight-loader/action-client-wrapper.js
./src/pages/midlands/index.tsx
Answered by risky
export async function getServerSideProps(ctx) {
  const { user } = await getSession(ctx.req, ctx.res);
  return { props: { foo: 'bar' } };
}
View full answer

28 Replies

Avatar
risky
"use server" is only for server actions
and are you using app or pages dir? as getServerSideProps is pages...
Avatar
Mini RexOP
pages dir
Avatar
risky
you don't need use server then (its a app dir thing)
Avatar
Mini RexOP
Alright.

This is my page:

import { getSession } from "@auth0/nextjs-auth0";

export async function getServerSideProps(context: any) {
  const session = await getSession(context);
}

export default async function Home() {

  return (
    <div className='h-screen flex items-center justify-center'>
      <div className="font-bold text-4xl">Midlands</div>
    </div>
  )
}


When this page loads, the following error occurs:
Server Error
Error: Invariant: cookies() expects to have requestAsyncStorage, none available.

This error happened while generating the page. Any console logs will be displayed in the terminal window.
Source
src\pages\midlands\index.tsx (4:18) @ async getServerSideProps

  2 | 
  3 | export async function getServerSideProps(context: any) {
> 4 | const session = await getSession(context);
    |                ^
  5 | }
  6 | 
  7 | export default async function Home() {


I'm assuming I've just done everything wrong; but when I researched that error, the suggested solution in a number of threads was to use "use server".
.
To clarify what I am trying to achieve:
I'm using auth0, and currently am storing the users "roles" in their idToken, which I can access through:
user["http://localhost:3000/roles"]


I want to create a system that will only allow access to a page if the user has the required role in order to access it, and I am honestly stumped with what to do; my research has just led me around in circles so far.
Avatar
risky
does this work to get cookies: https://stackoverflow.com/a/63875689
as that cookies method you are currently using iirc is for app dir
Avatar
Mini RexOP
It's throwing this error:
Server Error
Error: Objects are not valid as a React child (found: [object Promise]). If you meant to render a collection of children, use an array instead.
Avatar
risky
so i think this is how you do getSession for pages dir: https://github.com/auth0/nextjs-auth0/blob/main/src/session/get-session.ts#L91-L94
Avatar
risky
export async function getServerSideProps(ctx) {
  const { user } = await getSession(ctx.req, ctx.res);
  return { props: { foo: 'bar' } };
}
Answer
Avatar
Mini RexOP
Thanks for finding that for me.

I've just tried it now, and I no longer have any render errors, but neither of my console.log statements seem to be getting ran:

import { getSession } from '@auth0/nextjs-auth0';

export async function getServerSideProps(ctx) {
    const { user } = await getSession(ctx.req, ctx.res);
     console.log("Debug 1");
     console.log((user["http://localhost:3000/roles"] as string[]).join(", ").trimEnd());
    return { props: { foo: 'bar' } };
}

export default function Home() {

  return (
    <div className='h-screen flex items-center justify-center'>
      <div className="font-bold text-4xl">Midlands</div>
    </div>
  )
}
wait no I dont think that's how server side props works is it...
AHA

import { getSession } from '@auth0/nextjs-auth0';

export async function getServerSideProps(ctx) {
    const requiredRole = "midlands";

    const { user } = await getSession(ctx.req, ctx.res);
    if (!(user["http://localhost:3000/roles"] as string[]).includes(requiredRole)) {
      return {
        redirect: {
          destination: '/no-access',
          permanent: false,
        }
      }
    }
    return { props: { foo: 'bar' } };
}

export default function Home() {

  return (
    <div className='h-screen flex items-center justify-center'>
      <div className="font-bold text-4xl">Midlands</div>
    </div>
  )
}


got it. Cheers.
How would I move that logic into a seperate file so that I can easily use it across multiple pages?
Avatar
risky
do you have any utils folder or something
as you just need to create a file outside pages folder and you can import it
Avatar
Mini RexOP
yeah right, and I'm assuming I'd have to modify the authorisation a bit & then call it differently on the class I want to limit access to?
Avatar
risky
how much of the code is reusable?
like the whole getServerSideProps, or which section
Avatar
Mini RexOP
whole getServerSideProps, the only thing that would ever change is the requiredRole, that would be different for each page using it
Avatar
risky
yeah do you can make a function with the input param to be ctx and role required and just return that in server side props
Avatar
Mini RexOP
yep makes sense, & that wouldn't allow a user to modify the requiredRole through inspect element or anything would it?
Avatar
risky
no, everything is still on your server
effectivly copying the code but cleaner
you can show me to check tho
Avatar
Mini RexOP
👍 will do man, thanks for all of your help
Avatar
Mini RexOP
import Navbar from '@/components/Navbar';
import { getSession } from '@auth0/nextjs-auth0';

import { authorise } from '../../utils/PageAuth'

export async function getServerSideProps(ctx: any) {
  return authorise(ctx, "midlands");
}

export default function Home() {

  return (
    <div>
      <Navbar load={true}/>
      <div className='h-screen flex items-center justify-center'>
        <div className="font-bold text-4xl">Midlands</div>
      </div>
    </div>
  )
}


import { getSession } from "@auth0/nextjs-auth0";

export async function authorise(ctx: any, requiredRole: string) {
    const { user } = (await getSession(ctx.req, ctx.res)) as { user: any };
    if (!(user["http://localhost:3000/roles"] as string[]).includes(requiredRole)) {
      return {
        redirect: {
          destination: '/no-access',
          permanent: false,
        }
      }
    }
    return { props: { foo: 'bar' } };
}


That's what I ended up with, everything's working. tysm man, really appreciate it.