Next.js Discord

Discord Forum

Module not found Error when trying to use Server Actions

Unanswered
gin posted this in #help-forum
Open in Discord
ginOP
Module not found: Can't resolve 'react-server-dom-webpack/client'

177 Replies

ginOP
import { createSession } from "@/utils/user";


<form action={createSession}>
                                        <span data-uia="profile-button">
                                            <button type='submit' className="profile-button preferred-action">Login</button>
                                        </span>
                                    </form>


"use server";
export async function createSession() {
    console.log('createSession() called');
  
};
This should be the correct way to use Server Actions right?
Import trace for requested module:
./src/utils/user.tsx
./pages/index.tsx
 â—‹ Compiling /_error ...
 ⨯ ./node_modules/next/dist/build/webpack/loaders/next-flight-loader/action-client-wrapper.js:19:63
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/utils/user.tsx
./pages/index.tsx
Do you have it enabled in your next.config.js?
@Marchy Do you have it enabled in your next.config.js?
ginOP
/** @type {import('next').NextConfig} */
const nextConfig = {
    experimental: {
        serverActions: true,
    },
}

module.exports = nextConfig
â–² Next.js 13.5.3
  - Local:        http://localhost:3000
  - Environments: .env.local
  - Experiments (use at your own risk):
     · serverActions

 ✓ Ready in 3.7s
Maybe its how i render html?
Possibly, I don't see anything that jumps out at me with what you've shared so far
I would try to replicate it with a new page
in my root i have/pages/index.tsx
import Home from "@/app/Home/home";
import RootLayout from "@/app/layout";

export default function Indexpage() {


    return (
        <RootLayout>
            <Home />
        </RootLayout>
    );
}
And this is my RootLayout function
import '@/styles/main.scss';

export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {

return (
    <>
      <div className="rootLayout">
        <div className='appMountPoint'>{children}</div>
      </div>
    </>
  )
}
Oh, server actions are only in the app directory
@Marchy Oh, server actions are only in the app directory
ginOP
The Home function is in the app directory
@gin in my root i have/pages/index.tsx
👆
@Marchy 👆
ginOP
Wait thats the issue?
Why do you have a file in the pages directory?
@Marchy Why do you have a file in the pages directory?
ginOP
Because i wanted to make use of the routing feature in pages
Ah, yeah. Can't use both. It's either app or pages, both have file based routing
in app dir it's just /route/to/page.js
ginOP
Lemme try, if that solves issue i love you
@Marchy in app dir it's just `/route/to/page.js`
ginOP
"getServerSideProps" doesnt work in /app?
@gin That means i have to create a API endpoint to do something same in /app?
You don't need an API endpoint with server components usually. But if you do need one, those have been replaced with route handlers in the app dir
https://nextjs.org/docs/app/building-your-application/upgrading/app-router-migration#api-routes
Because i have to get some data from the client before i load the page
That worked well in /pages
Thats why i switched from create-react-app to next in the first place
@gin Wait i tought /app components are automatically client components and a rendered by the client?
They're pre-rendered to client components or serverless functions (SSR) automatically depending on what it needs. So if you access the database on the page level, that will run SSR. If you're fetching to an external API and it's cached, it may build static but regenerate on interval that you can configure
The compiler takes care of all that for you, but the conventions are different from the pages dir
Where are you requesting the data from? A database? an api endpoint?
@Marchy https://nextjs.org/docs/app/building-your-application/data-fetching
ginOP
Where exactly?
I only see that i have to create a route and use fetch
Well
Its a clientside database stored in a cookie
And the encryption is only possible on the server
@gin Its a clientside database stored in a cookie
Do you mean that you're using cookies for data storage?
@Marchy Do you mean that you're using cookies for data storage?
ginOP
Yes, iron-session i think it was called
😂
ginOP
Whats the Problem?
Oh just the session data?
@Marchy Oh just the session data?
ginOP
Just session data
I thought you meant like user data too for a second (cookies were actually used for general data storage years ago lool)
Are you trying to configure iron session with next specifically?
So i can say that the data is only stored on the users pc
Nothing saved on the server
So in that case, "data fetching" would all happen client side
are you using indexdb or local storage or something?
@Marchy are you using indexdb or local storage or something?
ginOP
Im not, the "data fetching" is only for getting the users prefered color or a saved avatar. That would be saved in the cookie. That cookie is encrypted by iron-session
And it can be only decrypted by the server
You can get the cookies here
ginOP
No, thats not the problem
@gin And it can be only decrypted by the server
by "on the server" do you mean you have a seperate backend?
@Marchy by "on the server" do you mean you have a seperate backend?
ginOP
I dont, that fetching happened before the html render in /pages
just like php
getServerSideProps
Then it return the html based of the props returned
I'm not sure if I'm understanding what you're asking. You're talking about storing data locally, but also needing to use getServerSideProps.
ginOP
So.

Im actually pretty good in making websites. Made plenty good websites using react and express for the Api.

This time i wanted to start with nextjs and i created a new project.
in /pages i have
index.tsx and browse.tsx

When the user goes on .org/browse the getServerSideProps checks for the session cookie. If its not present it prompts the user to go back to index.tsx
export default function Browse({ rs }: { rs: SUProp }) {
    return (
        <RootLayout>
            <>
                {rs && rs.showLogin ? <Login rs={rs} /> : <h1>Please go back to <a href="../">Home</a> to login</h1>} 
            </>
        </RootLayout>
    );
};

export const getServerSideProps = withIronSessionSsr(async (context) => {
    const rs: SUProp | undefined = context.req.session.user;

    if (!rs) {
        return {
            props: {
                rs: {
                    showLogin: false
                }
            }
        };
    }

    return {
        props: {
            rs
        }
    }
}, sessionOptions);

Get it? So i pass the returned prop to the function and then render based of the boolean.
The rest you can explain for yourself right?
Im listening to music and cant write a whole essay rn
Its a simple website with simple code.
it is nothing more and nothing less.
For me this isnt complicated and its fun @Marchy.
I could directly create the session on request yes, but i wanted to make it possible for the user to control his experience on the website
So, create a session with server actions
that was my goal
And i was sure i do this this in 2mins
You can handle the redirects for auth there by setting the matching paths
You can just configure it once now instead of needing to do it in getServerSideProps
There are some examples here with iron session specifically
https://github.com/vvo/iron-session/issues/560

But really, iron session is just wrapping cookie headers
@Marchy Ah, you're looking for middleware https://nextjs.org/docs/app/building-your-application/routing/middleware
ginOP
Middleware sounds cool, but how can i use the data i return?
I really want to reduce the usage of a booring api route.
@gin Middleware sounds cool, but how can i use the data i return?
You don't, middleware should be very slim because it runs before every request (for things like auth where you don't want to send ANY data to an unauthenticated user). Data you can just fetch from within the server component on the component level
like if you need to access cookies you can just

import { cookies } from 'next/headers'
 
export default function Page() {
  const cookieStore = cookies()
  const theme = cookieStore.get('theme')
  return '...'
}
middleware would be like using app.use(..)
@Marchy You don't, middleware should be very slim because it runs before every request (for things like auth where you don't want to send ANY data to an unauthenticated user). Data you can just fetch from within the server component on the component level
ginOP
My website is just 2-3 pages so yeah. Yk what? I will stay with /pages.
I will create 1-2 endpoints. One for creating a session and one for setting session data
@gin My website is just 2-3 pages so yeah. Yk what? I will stay with /pages. I will create 1-2 endpoints. One for creating a session and one for setting session data
That's perfectly acceptible, pages is still supported. Just won't get the react 18 features
I've been recommending app dir for more like application development where there's lots of moving parts
@Marchy That's perfectly acceptible, pages is still supported. Just won't get the react 18 features
ginOP
Wait so you telling me i cant just render some in /pages and some in /app?
If i want to make use of a new feature i could just render the route in /app
right
@gin Wait so you telling me i cant just render some in /pages and some in /app?
You can but it gets weird with the server-side stuff. They're technically deployed seperately
ginOP
Would be double work
so it'd be like maintining two seperate apps in the same repo
ginOP
hmm, yeah would extend the repo and make it more complicated
ohhh man
So i have to decide
app dir is better tbh, but it's very different from pages not just in code but in architecture so something to consider
ginOP
I want to use app
Only thing with the middlware i want to use the data returned as prop
Pass it directly to the component
I cant render the component in the middlware right?
:monkaLaugh:
@gin Only thing with the middlware i want to use the data returned as prop
This happens in your component, not in middleware. You just import the data fetching function directly
@Marchy This happens in your component, not in middleware. You just import the data fetching function directly
ginOP
yeah you told me that the middleware fetches data and then the page is rendered in the component
Cant i pass props from the middleware?
async function getData(){
    await new Promise(resolve => setTimeout(resolve, 1000));
    return {message: 'done'}
}

export default async function Home(){
    const {message} = await getData();
    return(
        <div>
            {message}
        </div>
    )

}

like this
@gin Cant i pass props from the middleware?
what would you be passing?
You can't do any data fetching within middleware
But you can read/set cookies
ginOP
Oh i cant?
I tought it is like the middleware in express
Nope, that means you'd have a hard request to your data source on every page load which is bad for performance
instead you can break it up with server components and stream them as they load
so you could have just a "nav" component that fetches (and caches!) the user data
ginOP
and what if i want to make use of the data outside of that component?
or like a data table that saves to a database
@gin and what if i want to make use of the data outside of that component?
pass it as props, pass it as context, or just fetch it again where you need it in a different component. Next automatically de-dupes requests.
props and context are the react-level way to pass things around, but generally you can avoid it by just using server code directly. It's much more like old PHP
Thats what im trying to do in this project
Like php
https://nextjs.org/docs/app/api-reference/functions/server-actions
This is where a lot of the magic happens in app dir
ginOP
Put on cloudflare and boom nobody abusing your api
@gin Put on cloudflare and boom nobody abusing your api
Can't abuse an api if you don't have one :thinkaboutit:
Hold on can i just fetch data using server actions on page load?
@gin Hold on can i just fetch data using server actions on page load?
Well, it doesn't exactly happen on page load but yes
ginOP
HMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
NOOOOOOOOOOOOOOOOOOOOO
no
well
It might be pre-cached by the serverless function and rendered as static depending on how you're fetching it
ginOP
nvm
but it executes only on page load
ginOP
That would reload the page twice or nah?
Load it once
And then post request on the same site
@gin Load it once
nope, requests are deduped
Next will try to pre-render everything it can to re-use all of your components as static HTML. Everything else it fills in on request
this talks about pages dir, but same principal just different framework with app dir
ginOP
But server actions would be like passing a paremeter to the page
?blablabla=123
Thats also not nice
@gin But server actions would be like passing a paremeter to the page
nope, no more passing props. Params still get passed into the folder name as [param] but you just await the result of the server code directly
async function getData(param){
    await new Promise(resolve => setTimeout(resolve, 1000));
    return {message: 'done'}
}

export default async function Home({params}){
    const {message} = await getData(params.id);
    return(
        <div>
            {message}
        </div>
    )

}
ginOP
So if i use server actions and render the page in app it will act like getServerSideProps in /pages?
And in that server action i can get the context?
Request Object for example
Or Cookies
kind of
that's where things get a little weird. There really is no such thing as a "request object" anymore because everything is pieced out
generally, you won't actually need the whole request object
and if you do that's kinda code smell
ginOP
lol
So
Cookies (auth stuff) you can still access directly
but generally you're only fetching exactly what you need to render the component
also authentication cookies get applied automatically when using fetch for posting data
ginOP
My brain is exploding rn even tho it easy. Like actually
I understand everything and i want to discuss but
Im awake too long
@gin My brain is exploding rn even tho it easy. Like actually
lool, 99% of the issues I've seen people run into next is because they're trying to do too much instead of just letting the framework handle it 😂
@gin Im awake too long
Get some sleep, i'll be around 👍
Fixed it with:
Having the /app only handling the Indexpage
So i can use server actions
Rest is done in /pages
👍
:meow_party:
:nice: