Next.js Discord

Discord Forum

How do I get NextAuth session outside of components?

Unanswered
blahaj.bitch posted this in #help-forum
Open in Discord
Avatar
I can't seem to find a documented way to do it, and whenever I try it, I need to use a SessionProvider, which isn't possible for how I have my site built.

81 Replies

Avatar
Also, I'm using App Router
Avatar
Tomistoma
What version of next-auth are you using? Also, why isn't using a SessionProvider an option? Are you getting the session data inside a client component or a server component?
Avatar
that depends on which side you are.

If you are on the serverside you can get your auth everywhere by doing
const session = await getServerSession(authOptions);

If you are on the clientside you can get it via the useSession hook:
const session = useSession();
Avatar
client component (page.tsx)
 ⨯ Error: [next-auth]: `useSession` must be wrapped in a <SessionProvider />
    at useSession (/home/nova/Desktop/dev.electric.carbon/.next/server/chunks/ssr/node_modules_ea690b._.js:14204:15)
    at Page (/home/nova/Desktop/dev.electric.carbon/.next/server/chunks/ssr/[root of the server]__1f8803._.js:87:182)
digest: "516915812"
 GET / 500 in 3682ms
Avatar
Tomistoma
Just wrap your layout with the SessionProvider and use the useSession() hook stated above. Do you need help setting up SessionProvider instead?
Avatar
unsure of how to do that
Avatar
Tomistoma
That's the issue.
Avatar
what you can also do is that you make your page.tsx as server component and pass the session to the client component down
Avatar
because my layout is built by functions with basically no actual base page
what page returns:
return (
    <>
        <div style={{ display: 'flex', margin: '0px' }}>
            <div style={{ width: '200px', backgroundColor: '#111111', margin: '0px', height: '100vh', marginRight: '10px' }} id='sidebar'>
                {}
            </div>
            <div style={{ flex: 1 }} id='page'>
                {}
            </div>
        </div>
    </>
);
Avatar
Tomistoma
Can you give me your layout.jsx?
Avatar
layout or page?
Avatar
Tomistoma
layout
Avatar
oh wait
import type { Metadata } from "next";
import localFont from "next/font/local";
import "./globals.css";

const jbm = localFont({
    variable: "--jbm",
    weight: "100 900",
    src: "./fonts/JetBrainsMonoNerdFont-Regular.ttf",
});

export const metadata: Metadata = {
    title: "Carbon",
    description: "Making in-game items truly yours.",
};

export default function RootLayout({
    children,
}: Readonly<{
    children: React.ReactNode;
}>) {
    return (
        <html lang="en">
            <body
                className={`${jbm.variable} antialiased`}
            >
                {children}
            </body>
        </html>
    );
}
i completely forgot that layout.tsx even exists 😭
Avatar
Tomistoma
You can follow this too.

1. Create a session-provider.jsx then paste this code:
"use client";

import { SessionProvider as Provider } from "next-auth/react";

export default function SessionProvider({ children }) {
  return <Provider>{children}</Provider>;
}

2. Go to your layout.jsx and integrate your SessionProvider.
<SessionProvider>
       <html lang="en">
            <body
                className={`${jbm.variable} antialiased`}
            >
                {children}
            </body>
        </html>
</SessionProvider>
You won't be able to use SessionProvider directly from next-auth because that would need to be in a client component. You can use it if you want your layout.tsx to be a client component but that's not recommended.
Avatar
so how do i do it otherwise?
Avatar
Tomistoma
Follow the instruction I sent
Avatar
layout.tsx:
Cannot find name 'SessionProvider'.
Avatar
Tomistoma
Yeah you need to import it.
I usually create that session-provider.jsx under a components folder.

If that's the case then do this:

import SessionProvider from "@/components/session-provider";
Avatar
page is router spamming
[next-auth][error][CLIENT_FETCH_ERROR] "\nhttps://next-auth.js.org/errors#client_fetch_error" "JSON.parse: unexpected character at line 1 column 1 of the JSON data" {}
Avatar
Tomistoma
Can I see your full layout and page?
Avatar
layout.tsx:
import type { Metadata } from "next";
import localFont from "next/font/local";
import "./globals.css";
import SessionProvider from "./session-provider";

const jbm = localFont({
    variable: "--jbm",
    weight: "100 900",
    src: "./fonts/JetBrainsMonoNerdFont-Regular.ttf",
});

export const metadata: Metadata = {
    title: "Carbon",
    description: "Making in-game items truly yours.",
};

export default function RootLayout({
    children,
}: Readonly<{
    children: React.ReactNode;
}>) {
    return (
        <SessionProvider>
            <html lang="en">
                <body
                    className={`${jbm.variable} antialiased`}
                >
                    {children}
                </body>
            </html>
        </SessionProvider>
    );
}
page.tsx:
Image
Avatar
Tomistoma
The issue is in your page.tsx.

useEffect(() => {
        loadPage();
    });


This is a bad use of useEffect
Avatar
sorry that its really long, im trying to shorten it by using next-auth and stuff like that
Avatar
Tomistoma
Yeah. Your page.tsx is bloated. At least separate the components entirely.
Avatar
why don't use use the CredentialsProvider from next-auth?
Avatar
gonna do that after fixing this
sorry?
Avatar
is there any reason for that?
Avatar
oh wait
i am using it
import NextAuth from "next-auth"
import CredentialsProvider from "next-auth/providers/credentials"
import { initialisemongoose } from "../[route]/route"
import { UserModel } from "../../mongoosemodels"
import { sha512 } from "js-sha512"

export const authOptions = {
    providers : [
        CredentialsProvider({
            name: 'Credentials',
            credentials: {
                username: { label: "Username", type: "text", placeholder: "johndoe" },
                password: {  label: "Password", type: "password" }
            },
            async authorize(credentials) {
                if (!credentials) {
                    throw new Error('Credentials are required');
                }
                const { username, password } = credentials;
                initialisemongoose();
                try {
                    const userDoc = await UserModel.findOne({ username });
                    if (userDoc) {
                        if (userDoc?.pwdhash && userDoc?.salt) {
                            const pwdhash = sha512(password + userDoc.salt);
                            if (pwdhash === userDoc.pwdhash) {
                                return {
                                    id: userDoc._id ? userDoc._id.toString() : '',
                                    name: userDoc.username ? userDoc.username : '',
                                }
                            } else {
                                return null;
                            }
                        } else {
                            return null;
                        }
                    }
                } catch (err) {
                    console.error(err);
                    return null;
                }
                return null;
            }
        })
    ],
}

export default NextAuth(authOptions);
Avatar
this doesn't look like you using it
Image
Avatar
thats the old login function that isnt used
Image
Avatar
when thats the old function, how do you login now?
Avatar
im leaving it as a point of reference
loadPage()
line 173
in page.tsx
Avatar
yea, my screenshot is from there
Avatar
doesnt match up with what im seeing
Image
Avatar
ah I missed that one. Sorry I am not that good in not that good code. My bad. Is there any reason why you don't use the routing of nextjs?
Avatar
all good, wdym why dont i use routing?
with next router?
Avatar
I am talking about the fundamentals of nextjs:
https://nextjs.org/docs/app/building-your-application/routing
Avatar
Tomistoma
Yeah, it's also painful to see document.getElementById, it feels like vanilla JS
Avatar
yep, yep
my next app is built entirely in app router
Avatar
yes, so back to my initial question:
Is there any reason why you don't use the routing of nextjs?
Avatar
wdym by that?
in what way?
Avatar
I am talking about the fundamentals of nextjs:
https://nextjs.org/docs/app/building-your-application/routing

Click the link, and read. Read, what I mean
Avatar
im still not sure
Avatar
not sure about?
Avatar
are you referring to why im not using both app and pages?
Avatar
Tomistoma
It's because you created some components and tried to render them in loadPage()
It's not ideal in next JS
Avatar
yeah
oh...
Avatar
Tomistoma
You can create separate components then load them to your page.tsx rather than having them inside the Page()
Avatar
i tried that with the sidebar in my app and got really confused really quickly
Avatar
Tomistoma
This is also an antipattern of React itself. Don't create components within components, just create a separate on entirely
Avatar
It seems like you are new in nextjs. In developement you can't just start by watching a youtube video or ask other people and follow every step the guy in the video does or someone said to you. That works, until you get an error. So start by learning the basics and then one after another. Right now it seems like you are learning React, Nextjs and JSX.

That's way to much to start. So, start with the basics: Javascript, CSS, HTML. Then go in the advanced direction: JSX, React, important Libraries. And then go in the OP stuff like: NextJs and Typescript.
It looks like you already know the basics like Javascript, CSS and HTML, so go now to JSX and React

I learned all these stuff from this guy: [Codevolution](https://www.youtube.com/@Codevolution)
Very much recommended.

For the beginning I recommend you, you using his crash course, for the topics I wrote down: https://www.youtube.com/watch?v=jLS0TkAHvRg&list=PLC3y8-rFHvwhuX4qGvFx-wPy_MEi6Jdp7&index=8

If you just want to learn nextjs, you might want to start their learning couse: https://nextjs.org/learn

Please do it, else you won't make it that long in programming
After this playlist you know the basics of webdevelopement and can start big projects like a ecommerce store.

Enjoy the developement journey and best of luck ^^
Avatar
Tomistoma
This is what you should've done.

Create the sidebar in another file.
export function Sidebar(){
...
}


import the sidebar in page.tsx and just call it.

return(
<>
  <Sidebar/>
</>)
Avatar
i did exactly that
might be a good idea
im really lost :p
Avatar
Tomistoma
You can leave me a dm if it's just the basics or if you were having issues implementing standard React patterns.
Avatar
alright
Avatar
i think i figured out why i was having issues, i just undid to when i made it
found this error
Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
1. You might have mismatching versions of React and the renderer (such as React DOM)
2. You might be breaking the Rules of Hooks
3. You might have more than one copy of React in the same app
See https://react.dev/link/invalid-hook-call for tips about how to debug and fix this problem.
 ⨯ TypeError: Cannot read properties of null (reading 'useContext')
    at useRouter (/home/nova/Desktop/dev.electric.carbon/.next/server/chunks/ssr/node_modules_next_3478ec._.js:1285:42)
    at [project]/app/components/sidebar.tsx [app-ssr] (ecmascript) (/home/nova/Desktop/dev.electric.carbon/.next/server/chunks/ssr/[root of the server]__dac2ff._.js:73:164)
    at instantiateModule (/home/nova/Desktop/dev.electric.carbon/.next/server/chunks/ssr/[turbopack]_runtime.js:589:23)
    at getOrInstantiateModuleFromParent (/home/nova/Desktop/dev.electric.carbon/.next/server/chunks/ssr/[turbopack]_runtime.js:644:12)
    at esmImport (/home/nova/Desktop/dev.electric.carbon/.next/server/chunks/ssr/[turbopack]_runtime.js:132:20)
    at [project]/app/page.tsx [app-ssr] (ecmascript) (/home/nova/Desktop/dev.electric.carbon/.next/server/chunks/ssr/[root of the server]__dac2ff._.js:239:133)
    at instantiateModule (/home/nova/Desktop/dev.electric.carbon/.next/server/chunks/ssr/[turbopack]_runtime.js:589:23)
    at getOrInstantiateModuleFromParent (/home/nova/Desktop/dev.electric.carbon/.next/server/chunks/ssr/[turbopack]_runtime.js:644:12)
    at commonJsRequire (/home/nova/Desktop/dev.electric.carbon/.next/server/chunks/ssr/[turbopack]_runtime.js:147:20)
digest: "193160438"
 GET / 500 in 2952ms
this is when using my sidebar as a component