Next.js Discord

Discord Forum

How do I get NextAuth session outside of components?

Unanswered
Transvaal lion posted this in #help-forum
Open in Discord
Transvaal lionOP
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

Transvaal lionOP
Also, I'm using App Router
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?
@Transvaal lion 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.
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();
 ⨯ 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
@Transvaal lion client component (page.tsx)
Just wrap your layout with the SessionProvider and use the useSession() hook stated above. Do you need help setting up SessionProvider instead?
Transvaal lionOP
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>
    </>
);
Can you give me your layout.jsx?
Transvaal lionOP
layout or page?
@Transvaal lion layout or page?
layout
Transvaal lionOP
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 😭
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.
@Transvaal lion so how do i do it otherwise?
Follow the instruction I sent
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";
Transvaal lionOP
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" {}
Can I see your full layout and page?
@Brokenwind Can I see your full layout and page?
Transvaal lionOP
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:
The issue is in your page.tsx.

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


This is a bad use of useEffect
@Transvaal lion page.tsx:
Transvaal lionOP
sorry that its really long, im trying to shorten it by using next-auth and stuff like that
Yeah. Your page.tsx is bloated. At least separate the components entirely.
@Transvaal lion sorry that its really long, im trying to shorten it by using next-auth and stuff like that
why don't use use the CredentialsProvider from next-auth?
@Brokenwind Yeah. Your page.tsx is bloated. At least separate the components entirely.
Transvaal lionOP
gonna do that after fixing this
@B33fb0n3 why don't use use the CredentialsProvider from next-auth?
Transvaal lionOP
sorry?
@Transvaal lion sorry?
is there any reason for that?
Transvaal lionOP
oh wait
@B33fb0n3 is there any reason for that?
Transvaal lionOP
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);
@Transvaal lion i am using it
this doesn't look like you using it
@B33fb0n3 this doesn't look like you using it
Transvaal lionOP
thats the old login function that isnt used
@Transvaal lion thats the old login function that isnt used
when thats the old function, how do you login now?
Transvaal lionOP
im leaving it as a point of reference
@B33fb0n3 when thats the old function, how do you login now?
Transvaal lionOP
loadPage()
line 173
in page.tsx
@Transvaal lion line 173
yea, my screenshot is from there
@B33fb0n3 yea, my screenshot is from there
Transvaal lionOP
doesnt match up with what im seeing
@Transvaal lion doesnt match up with what im seeing
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?
with next router?
Yeah, it's also painful to see document.getElementById, it feels like vanilla JS
@B33fb0n3 I am talking about the fundamentals of nextjs: https://nextjs.org/docs/app/building-your-application/routing
Transvaal lionOP
my next app is built entirely in app router
@Transvaal lion my next app is built entirely in app router
yes, so back to my initial question:
Is there any reason why you don't use the routing of nextjs?
in what way?
@Transvaal lion wdym by that?
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
@Transvaal lion im still not sure
not sure about?
Transvaal lionOP
are you referring to why im not using both app and pages?
It's because you created some components and tried to render them in loadPage()
It's not ideal in next JS
@Brokenwind It's not ideal in next JS
Transvaal lionOP
oh...
You can create separate components then load them to your page.tsx rather than having them inside the Page()
@Brokenwind You can create separate components then load them to your page.tsx rather than having them inside the Page()
Transvaal lionOP
i tried that with the sidebar in my app and got really confused really quickly
This is also an antipattern of React itself. Don't create components within components, just create a separate on entirely
@Transvaal lion i tried that with the sidebar in my app and got really confused really quickly
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 ^^
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/>
</>)
You can leave me a dm if it's just the basics or if you were having issues implementing standard React patterns.
Transvaal lionOP
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