How do I get NextAuth session outside of components?
Unanswered
blahaj.bitch posted this in #help-forum
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
Also, I'm using App Router
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?
that depends on which side you are.
If you are on the serverside you can get your auth everywhere by doing
If you are on the clientside you can get it via the useSession hook:
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();
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
Tomistoma
Just wrap your layout with the SessionProvider and use the
useSession()
hook stated above. Do you need help setting up SessionProvider instead?unsure of how to do that
Tomistoma
That's the issue.
what you can also do is that you make your page.tsx as server component and pass the session to the client component down
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>
</>
);
Tomistoma
Can you give me your layout.jsx?
layout or page?
Tomistoma
layout
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 😭
Tomistoma
You can follow this too.
1. Create a session-provider.jsx then paste this code:
2. Go to your layout.jsx and integrate your SessionProvider.
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.
so how do i do it otherwise?
Tomistoma
Follow the instruction I sent
layout.tsx:
Cannot find name 'SessionProvider'.
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:
If that's the case then do this:
import SessionProvider from "@/components/session-provider";
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" {}
Tomistoma
Can I see your full layout and page?
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:
Tomistoma
The issue is in your page.tsx.
This is a bad use of useEffect
useEffect(() => {
loadPage();
});
This is a bad use of useEffect
sorry that its really long, im trying to shorten it by using next-auth and stuff like that
Tomistoma
Yeah. Your page.tsx is bloated. At least separate the components entirely.
why don't use use the
CredentialsProvider
from next-auth?gonna do that after fixing this
sorry?
is there any reason for that?
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);
thats the old login function that isnt used
when thats the old function, how do you login now?
yea, my screenshot is from there
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?
all good, wdym why dont i use routing?
with next router?
I am talking about the fundamentals of nextjs:
https://nextjs.org/docs/app/building-your-application/routing
https://nextjs.org/docs/app/building-your-application/routing
Tomistoma
Yeah, it's also painful to see document.getElementById, it feels like vanilla JS
yep, yep
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?
wdym by that?
in what way?
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
https://nextjs.org/docs/app/building-your-application/routing
Click the link, and read. Read, what I mean
im still not sure
not sure about?
are you referring to why im not using both app and pages?
Tomistoma
It's because you created some components and tried to render them in loadPage()
It's not ideal in next JS
yeah
oh...
Tomistoma
You can create separate components then load them to your page.tsx rather than having them inside the Page()
i tried that with the sidebar in my app and got really confused really quickly
Tomistoma
This is also an antipattern of React itself. Don't create components within components, just create a separate on entirely
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 ^^
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 ^^
Tomistoma
This is what you should've done.
Create the sidebar in another file.
import the sidebar in page.tsx and just call it.
Create the sidebar in another file.
export function Sidebar(){
...
}
import the sidebar in page.tsx and just call it.
return(
<>
<Sidebar/>
</>)
Tomistoma
You can leave me a dm if it's just the basics or if you were having issues implementing standard React patterns.
alright
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