Displaying data from my Postgres database.
Answered
! nolikas posted this in #help-forum
How do I display data on my website (such as user email) when I use
useState() ? To get data, I use this code:-> auth-status.tsx
import { getServerSession } from "next-auth/next";
export default async function AuthStatus() {
const session = await getServerSession();
return (
<div className="w-full flex justify-center items-center">
{session && (
<p className="">
{session.user?.email}
</p>
)}
</div>
);
}211 Replies
I need
useState() for my sidebar@! nolikas I need `useState()` for my sidebar
create the sidebar with a client component then import it in server component
@! nolikas you can even use a client component end store the state inside this client component or you can fetch it serverside in a server component. I recommend you to not use useState, because you can run into stale data. So I would use a fetch call everytime when the component is rendered. Nextjs has good caching mechanisms, so you can easily do that, without having more request: so it‘s easier for you, and you won’t have stale data 🙂
@Ray create the sidebar with a client component then import it in server component
Oh, it would make sense 🙂
But..
I need to use the data IN the sidebar
@! nolikas I need to use the data IN the sidebar
you can pass the data to it from the server component
Okay, but I think I have one problem
I'm basically using TailwindUI's sidebar
And all content of my website is built in the div of sidebar
<div>
{/* ... Sidebar Start ... */}
...
{/* ... Sidebar End ... */}
<main className="py-10 lg:pl-72 bg-zinc-900 h-screen">
<div className="px-4 sm:px-6 lg:px-8">
{/* MAIN PAGE CONTENT */}
<div className="flex flex-col space-y-5 justify-center items-center bg-zinc-900">
{/* <Suspense fallback="Loading..."> */}
{/* </Suspense> */}
</div>
</div>
</main>
</div>@Ray
@! nolikas tsx
<div>
{/* ... Sidebar Start ... */}
...
{/* ... Sidebar End ... */}
<main className="py-10 lg:pl-72 bg-zinc-900 h-screen">
<div className="px-4 sm:px-6 lg:px-8">
{/* MAIN PAGE CONTENT */}
<div className="flex flex-col space-y-5 justify-center items-center bg-zinc-900">
{/* <Suspense fallback="Loading..."> */}
{/* </Suspense> */}
</div>
</div>
</main>
</div>
yea, you can pass all the data from the server component to the client component
@B33fb0n3 yea, you can pass all the data from the server component to the client component
This is what I have right now
If I put
###
<AuthStatus /> element to that code in Suspense, I get error with client/server components.###
auth-status.tsximport { getServerSession } from "next-auth/next";
export default async function AuthStatus() {
const session = await getServerSession();
return (
<div className="w-full flex justify-center items-center">
{session && (
<p className="">
{session.user?.email}
</p>
)}
</div>
);
}you can put the content you want to be inside of the sidebar as the children props like this
<Sidebar>
<div>other content</div>
</Sidebar>then in the sidebar component render like this
function Sidebar({children}:{children:ReactNode}) {
return (
<aside>
<nav>....</nav>
{children}
</aside>
)
}how you render this component?
<div className="flex flex-col space-y-5 justify-center items-center bg-zinc-900">
<Suspense fallback="Loading...">
<AuthStatus />
</Suspense>
</div>the getServerSession is from next-auth?
Yes
import { getServerSession } from "next-auth/next";
export default async function AuthStatus() {
const session = await getServerSession();
return (
<div className="w-full flex justify-center items-center">
{session && (
<p className="">
{session.user?.email}
</p>
)}
</div>
);
}Full code of
auth-status.tsxwhat version of next-auth are you using?
"next-auth": "^4.24.5", in package.jsonIf this is the right way to check it
try next-auth@beta
"next-auth": "^5.0.0-beta.4",npm ERR! code ERESOLVE
npm ERR! ERESOLVE could not resolve
npm ERR!
npm ERR! While resolving: next-auth@5.0.0-beta.4
npm ERR! Found: next@13.5.6
npm ERR! node_modules/next
npm ERR! next@"^13.4.2" from the root project
npm ERR!
npm ERR! Could not resolve dependency:
npm ERR! peer next@"^14" from next-auth@5.0.0-beta.4
npm ERR! node_modules/next-auth
npm ERR! next-auth@"^5.0.0-beta.4" from the root project
npm ERR!
npm ERR! Conflicting peer dependency: next@14.0.3
npm ERR! node_modules/next
npm ERR! peer next@"^14" from next-auth@5.0.0-beta.4
npm ERR! node_modules/next-auth
npm ERR! next-auth@"^5.0.0-beta.4" from the root project
npm ERR!
npm ERR! Fix the upstream dependency conflict, or retry
npm ERR! this command with --force or --legacy-peer-deps
npm ERR! to accept an incorrect (and potentially broken) dependency resolution.I also get this when I try to run
npm i next-auth@betayou using next 13?
Need to update?
If there are no breaking changes then sure 🙂
no breaking change from next 13
I heard it's pain to move from 12 to 13 xd
14.0.3 latest?
Server Error
ReferenceError: "next-auth/jwt" is deprecated. If you are not ready to migrate, keep using "next-auth@4".
Read more on https://authjs.dev/guides/upgrade-to-v5
This error happened while generating the page. Any console logs will be displayed in the terminal window.When I open the website
yes
Also my
middleware.ts:import { getToken } from "next-auth/jwt";
import { NextRequest, NextResponse } from "next/server";
export default async function middleware(req: NextRequest) {
const path = req.nextUrl.pathname;
if (path === "/") {
return NextResponse.next();
}
const session = await getToken({
req,
secret: process.env.NEXTAUTH_SECRET,
});
if (!session && path === "/dashboard") {
return NextResponse.redirect(new URL("/login", req.url));
} else if (session && (path === "/login" || path === "/register")) {
return NextResponse.redirect(new URL("/dashboard", req.url));
}
return NextResponse.next();
}With this error:
Module '"next-auth/jwt"' has no exported member 'getToken'.ts(2305)
import getTokencheck the example
export { auth as middleware } from "auth"
// Read more: https://nextjs.org/docs/app/building-your-application/routing/middleware#matcher
export const config = {
matcher: ["/((?!api|_next/static|_next/image|favicon.ico).*)"],
}next-auth v5 middleware look like this
so replace everything with this?
yes
Module not found: Can't resolve 'auth'
23 |
24 |
> 25 | export { auth as middleware } from "auth"
26 |
27 | // Read more: https://nextjs.org/docs/app/building-your-application/routing/middleware#matcher
28 | export const config = {
https://nextjs.org/docs/messages/module-not-foundyou can do the redirect like this
export const authConfig = {
providers: [],
callbacks: {
authorized({ auth, request: { nextUrl } }) {
const isLoggedIn = !!auth?.user;
const isOnDashboard = nextUrl.pathname.startsWith("/dashboard");
if (isOnDashboard) {
if (isLoggedIn) return true;
return false;
} else if (isLoggedIn) {
return Response.redirect(new URL("/dashboard", nextUrl));
}
return true;
},
},
} satisfies NextAuthConfig;well auth is the next auth config file
@Ray https://github.com/nextauthjs/next-auth-example
check out this example
you can put it in other place
yes auth.ts in the example
you can use any filename you like tho
I'm a bit lost
So I have
auth.ts and middleware.ts right?well the auth.ts is where you export the NextAuth, you can put it in other place or keep it as auth.ts
the example put it in root, so in the middleware, they just import from root
import NextAuth from "next-auth"
import type { NextAuthConfig } from "next-auth"
export const authConfig = {
providers: [],
callbacks: {
authorized({ auth, request: { nextUrl } }) {
const isLoggedIn = !!auth?.user;
const isOnDashboard = nextUrl.pathname.startsWith("/dashboard");
if (isOnDashboard) {
if (isLoggedIn) return true;
return false;
} else if (isLoggedIn) {
return Response.redirect(new URL("/dashboard", nextUrl));
}
return true;
},
},
} satisfies NextAuthConfig; Here's how my auth.ts looks I need to change anything or no?if you put inside app folder, then you have to change the import path to 'app/auth'
@Ray if you put inside app folder, then you have to change the import path to 'app/auth'
I will hold it in root if it's ok
export const { handlers, auth, signIn, signOut } = NextAuth(authConfig)try restart typescript server
Ok I'll be back to pc in couple mins
Now
@! nolikas So I have `auth.ts` and `middleware.ts` right?
What should be put in my middleware.ts?
export { auth as middleware } from "auth"
// Read more: https://nextjs.org/docs/app/building-your-application/routing/middleware#matcher
export const config = {
matcher: ["/((?!api|_next/static|_next/image|favicon.ico).*)"],
}what is your api route?
import { handlers } from "auth"
export const { GET, POST } = handlershave you change it?
oh wait
route.ts at [...nextauth]:import NextAuth, { type NextAuthOptions } from "next-auth";
import CredentialsProvider from "next-auth/providers/credentials";
import prisma from "@/lib/prisma";
import { compare } from "bcrypt";
export const authOptions: NextAuthOptions = {
providers: [
CredentialsProvider({
credentials: {
email: { label: "Email", type: "email" },
password: { label: "Password", type: "password" }
},
async authorize(credentials) {
const { email, password } = credentials ?? {}
if (!email || !password) {
throw new Error("Missing username or password");
}
const user = await prisma.user.findUnique({
where: {
email,
},
});
// if user doesn't exist or password doesn't match
if (!user || !(await compare(password, user.password))) {
throw new Error("Invalid username or password");
}
return user;
},
}),
],
};
const handler = NextAuth(authOptions);
export { handler as GET, handler as POST };the provider logic move to
auth.tsSo the
const handler = ... should be with all of authOptions in auth.tsthe handler is exporting from
auth.tsSorry bro, I'm kinda lost 😅
lol
can you format whole
auth.tx for me?// auth.ts
export const authConfig = {
providers: [
CredentialsProvider({
credentials: {
email: { label: "Email", type: "email" },
password: { label: "Password", type: "password" },
},
async authorize(credentials) {
const { email, password } = credentials ?? {};
if (!email || !password) {
throw new Error("Missing username or password");
}
const user = await prisma.user.findUnique({
where: {
email,
},
});
// if user doesn't exist or password doesn't match
if (!user || !(await compare(password, user.password))) {
throw new Error("Invalid username or password");
}
return user;
},
}),
],
callbacks: {
authorized({ auth, request: { nextUrl } }) {
const isLoggedIn = !!auth?.user;
const isOnDashboard = nextUrl.pathname.startsWith("/dashboard");
if (isOnDashboard) {
if (isLoggedIn) return true;
return false;
} else if (isLoggedIn) {
return Response.redirect(new URL("/dashboard", nextUrl));
}
return true;
},
},
} satisfies NextAuthConfig;
export const { handlers, auth, signIn, signOut } = NextAuth(authConfig)// app/api/auth/[...nextauth]/route.ts
import { handlers } from "auth"
export const { GET, POST } = handlers// middleware.ts
export { auth as middleware } from "auth"
// Read more: https://nextjs.org/docs/app/building-your-application/routing/middleware#matcher
export const config = {
matcher: ["/((?!api|_next/static|_next/image|favicon.ico).*)"],
}is your CredentialProvider import from "next-auth/providers/credentials"
import CredentialsProvider from "next-auth/providers/credentials";yup
here all imports:
import NextAuth from "next-auth"
import type { NextAuthConfig } from "next-auth"
import CredentialsProvider from "next-auth/providers/credentials";
import prisma from "@/lib/prisma";
import { compare } from "bcrypt";it all worked in next v13 btw
export const authConfig = {
providers: [
CredentialsProvider({
credentials: {
email: { label: "Email", type: "email" },
password: { label: "Password", type: "password" },
},
async authorize(credentials: {email:string; password: string}) {
const { email, password } = credentials ?? {};
if (!email || !password) {
throw new Error("Missing username or password");
}
const user = await prisma.user.findUnique({
where: {
email,
},
});
// if user doesn't exist or password doesn't match
if (!user || !(await compare(password, user.password))) {
throw new Error("Invalid username or password");
}
return user;
},
}),
],
callbacks: {
authorized({ auth, request: { nextUrl } }) {
const isLoggedIn = !!auth?.user;
const isOnDashboard = nextUrl.pathname.startsWith("/dashboard");
if (isOnDashboard) {
if (isLoggedIn) return true;
return false;
} else if (isLoggedIn) {
return Response.redirect(new URL("/dashboard", nextUrl));
}
return true;
},
},
} satisfies NextAuthConfig;
export const { handlers, auth, signIn, signOut } = NextAuth(authConfig)you need to type it
if you using zod, you can do something like this
Credentials({
async authorize(credentials) {
const parsedCredentials = z
.object({ email: z.string().email(), password: z.string().min(6) })
.safeParse(credentials);
if (parsedCredentials.success) {
const { email, password } = parsedCredentials.data;
const user = await getUser(email);
if (!user) return null;
const passwordsMatch = await bcrypt.compare(password, user.password);
if (passwordsMatch) return user;
return user;
}
return null;
},
}),Nope never heard of zod xd
nm just type it lol
still one left
The expected type comes from property 'authorize' which is declared here on type 'Partial<CredentialsConfig<{ email: { label: string; type: string; }; password: { label: string; type: string; }; }>>ok change to this
export const authConfig = {
providers: [
CredentialsProvider({
credentials: {
email: { label: "Email", type: "email" },
password: { label: "Password", type: "password" },
},
async authorize(credentials) {
const { email, password } = credentials as {email:string; password: string};
if (!email || !password) {
throw new Error("Missing username or password");
}
const user = await prisma.user.findUnique({
where: {
email,
},
});
// if user doesn't exist or password doesn't match
if (!user || !(await compare(password, user.password))) {
throw new Error("Invalid username or password");
}
return user;
},
}),
],
callbacks: {
authorized({ auth, request: { nextUrl } }) {
const isLoggedIn = !!auth?.user;
const isOnDashboard = nextUrl.pathname.startsWith("/dashboard");
if (isOnDashboard) {
if (isLoggedIn) return true;
return false;
} else if (isLoggedIn) {
return Response.redirect(new URL("/dashboard", nextUrl));
}
return true;
},
},
} satisfies NextAuthConfig;
export const { handlers, auth, signIn, signOut } = NextAuth(authConfig)credentials.d.ts(36, 5): The expected type comes from property 'authorize' which is declared here on type 'Partial<CredentialsConfig<{ email: { label: string; type: string; }; password: { label: string; type: string; }; }>>Still this
tried reloading ts client with no success
how about this
export const authConfig = {
providers: [
CredentialsProvider({
credentials: {
email: { label: "Email", type: "email" },
password: { label: "Password", type: "password" },
},
async authorize(credentials) {
const { email, password } = credentials as {email:string; password: string};
if (!email || !password) {
return null
}
const user = await prisma.user.findUnique({
where: {
email,
},
});
// if user doesn't exist or password doesn't match
if (!user || !(await compare(password, user.password))) {
return null
}
return user;
},
}),
],
callbacks: {
authorized({ auth, request: { nextUrl } }) {
const isLoggedIn = !!auth?.user;
const isOnDashboard = nextUrl.pathname.startsWith("/dashboard");
if (isOnDashboard) {
if (isLoggedIn) return true;
return false;
} else if (isLoggedIn) {
return Response.redirect(new URL("/dashboard", nextUrl));
}
return true;
},
},
} satisfies NextAuthConfig;
export const { handlers, auth, signIn, signOut } = NextAuth(authConfig)sec
Still same..
can you show the screenshot
export const authConfig = {
providers: [
CredentialsProvider({
credentials: {
email: { label: "Email", type: "email" },
password: { label: "Password", type: "password" },
},
async authorize(credentials) {
const { email, password } = credentials as {email:string; password: string};
if (!email || !password) {
return null
}
const user = await prisma.user.findUnique({
where: {
email,
},
});
if (!user) return null
// if user doesn't exist or password doesn't match
if (await compare(password, user.password)) {
return user
}
return null;
},
}),
],
callbacks: {
authorized({ auth, request: { nextUrl } }) {
const isLoggedIn = !!auth?.user;
const isOnDashboard = nextUrl.pathname.startsWith("/dashboard");
if (isOnDashboard) {
if (isLoggedIn) return true;
return false;
} else if (isLoggedIn) {
return Response.redirect(new URL("/dashboard", nextUrl));
}
return true;
},
},
} satisfies NextAuthConfig;
export const { handlers, auth, signIn, signOut } = NextAuth(authConfig)Still same 

✓ Ready in 7.7s
â—‹ Compiling /middleware ...
⨯ ./node_modules/@mapbox/node-pre-gyp/lib/util/nw-pre-gyp/index.html
Module parse failed: Unexpected token (1:0)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
> <!doctype html>
| <html>
| <head>
Import trace for requested module:
./node_modules/@mapbox/node-pre-gyp/lib/util/nw-pre-gyp/index.html
./node_modules/@mapbox/node-pre-gyp/lib/ sync ^\.\/.*$
./node_modules/@mapbox/node-pre-gyp/lib/node-pre-gyp.js
./node_modules/bcrypt/bcrypt.js
./auth.tsconsole tho
can you liveshare?
Not sure how it fully works
but here's the link
Done?
page loaded
ok wait
Unhandled Runtime Error
TypeError: URL constructor: /api/auth is not a valid URL.
Call Stack
signIn
node_modules\next-auth\react.js (157:0)after trying to login
try login again
import { signIn } from "auth";signIn need to be imported from
auth nowmiddleware redirects from /login to /dashboard
but in dashboard..
Failed to compile
./node_modules/@mapbox/node-pre-gyp/lib/util/nw-pre-gyp/index.html
Module parse failed: Unexpected token (1:0)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
> <!doctype html>
| <html>
| <head>
This error occurred during the build process and can only be dismissed by fixing the error.You see the console, right?
try again
Failed to compile
./node_modules/@mapbox/node-pre-gyp/lib/util/nw-pre-gyp/index.html
Module parse failed: Unexpected token (1:0)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
> <!doctype html>
| <html>
| <head>
Import trace for requested module:
./node_modules/@mapbox/node-pre-gyp/lib/util/nw-pre-gyp/index.html
./node_modules/@mapbox/node-pre-gyp/lib/ sync ^\.\/.*$
./node_modules/@mapbox/node-pre-gyp/lib/node-pre-gyp.js
./node_modules/bcrypt/bcrypt.js
./auth.ts
./components/form.tsx
This error occurred during the build process and can only be dismissed by fixing the error.try remove node_modules and reinstall
sure
does it work?
I think my pc did some shi
as the
npm i command is finished but doesnt continue with other commandsone sec
ah ok
do you have this installed?
bcrypt require it on window
started dev server
still same error after install
Failed to compile
./node_modules/@mapbox/node-pre-gyp/lib/util/nw-pre-gyp/index.html
Module parse failed: Unexpected token (1:0)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
> <!doctype html>
| <html>
| <head>
This error occurred during the build process and can only be dismissed by fixing the error.check
auth-status.tsx alsosome import error
import { auth } from "auth";use this instead in v5
dashboard loadeddd
tho throws one error:
which page is this?
/dashboard/page.tsx
ah i see the problem now
Answer
I see my bro is cooking now ::DD
does it work?
WORKS W NO ERRORS
server component cannot import in client component directly lol
and you need to fix the bcrypt issue
it is skipping password check now
I use this when i was development in window
@Ray it is skipping password check now
I see I see
One probably last thing
Any way to move the email to Sidebar?
yes
i show you
{/* CARD CONTENT */}
<div className="flex flex-col" tabIndex={0} role="button">
<span className="sr-only">Your profile</span>
<span className="text-sm font-semibold leading-6" aria-hidden="true">nolikaS</span>
{/* <span className="font-base text-sm text-gray-500"><AuthStatus /></span> */}
{/* DROPDOWN */}
<ul className="dropdown-content w-full -ml-[72px] z-30 p-2 menu shadow bg-zinc-900 rounded-t-xl items-center justify-center text-center">
<li className="w-full"><Link href="/account">Account</Link></li>
<li className="w-full"><SignOut /></li>
</ul>
</div>replace this?
<AuthStatus /> contains user's email
you prob need to uncomment that line and put some logic so it displays the email
like this?
i didnt login so i cannot see
Unhandled Runtime Error
ReferenceError: child is not defined
Source
app\dashboard\side-bar.tsx (166:25) @ child
164 | {/* <span className="sr-only">Your profile</span>
165 | <span className="text-sm font-semibold leading-6" aria-hidden="true">nolikaS</span> */}
> 166 | {child}
| ^
167 | {/* <span className="font-base text-sm text-gray-500"><AuthStatus /></span> */}
168 | {/* DROPDOWN */}
169 | <ul className="dropdown-content w-full -ml-[72px] z-30 p-2 menu shadow bg-zinc-900 rounded-t-xl@Ray change it to children
you forgot to save the file perhaps 🙂
as I saw that too
and now it's freaking workingggg
cool
remember to rename the _middleware.ts to middelware.ts after you fix the bcrypt issue
im gonna disconnect
right click > application