Next.js Discord

Discord Forum

Displaying data from my Postgres database.

Answered
! nolikas posted this in #help-forum
Open in Discord
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>
  );
}
Answered by Ray
ah i see the problem now
View full answer

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 🙂
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
If I put <AuthStatus /> element to that code in Suspense, I get error with client/server components.

### 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>
  );
}
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>
  )
}
@Ray what error you got?
Email shows up on the screen, but I get this in my terminal:
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.tsx
what version of next-auth are you using?
"next-auth": "^4.24.5", in package.json
If 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@beta
you using next 13?
@Ray you using next 13?
Yup
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 getToken
check 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-found
you 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'
export const { handlers, auth, signIn, signOut } = NextAuth(authConfig)
Binding element 'auth' implicitly has an 'any' type.
same for nextUrl
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).*)"],
}
@Ray try restart typescript server
okay this worked
When I log in...
I get this error in console:
what is your api route?
import { handlers } from "auth"
export const { GET, POST } = handlers

have 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.ts
So the const handler = ... should be with all of authOptions in auth.ts
the handler is exporting from auth.ts
Sorry 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).*)"],
}
Got some errors on auth.ts
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
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
sec
Here
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 :blobpensivesob:
 ✓ 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.ts
console tho
can you liveshare?
Not sure how it fully works
but here's the link
Done?
it is expecting the user.id is string
lol
let try
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 now
middleware 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 commands
one sec
ah ok
There is a chance that...
when I updated to v14
prisma didnt update
do you have this installed?
Still doesnt work
nope
didnt do it manually
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.
ok wait
could be problem with bcrypt
i commented it out and it run fine
check auth-status.tsx also
some 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
lol
change it to children
I see its children from my side
@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
Bro you goat frrr
tysm
looks good af ❤️
What do I mark as an answer here?
right click > application