Having trouble with 'use client' while logging in
Answered
Selkirk Rex posted this in #help-forum
Selkirk RexOP
So I'm trying to implement a simple credentials authentication with next-auth, and I'm having trouble rendering a button on my navbar as 'Sign in' or 'Sign out' based on whether the use is logged out or not.
Here's my code:
Here's my whole github repo for reference:
https://github.com/sanjana-bhat-2002/wordle-clone
Errors im getting: https://srcb.in/jLPnmaPUsW
I have not included the client component (UserNav) directly, based on the suggestion of this video:https://youtu.be/bicCg4GxOP8?si=VXAsNTynCbO8cMeM&t=3556
Here's my code:
//Navbar.tsx
import Link from 'next/link';
import { buttonVariants } from '@/UI/widgets/button';
import { HandMetal } from 'lucide-react';
import UserNav from './UserNav';
import { getServerSession } from 'next-auth';
import { authOptions } from '@/lib/auth';
const Navbar = async () => {
const session = await getServerSession(authOptions);
return (
<div className='bg-zinc-900 py-2 border-b border-s-zinc-200 fixed w-full z-10 top-0'>
<div className='container flex items-center justify-between'>
<Link href='/'>
<HandMetal />
</Link>
{session?.user ? (
<UserNav />
) : (
<Link className={buttonVariants()} href='/login'>
Sign in
</Link>
)}
</div>
</div>
);
};
export default Navbar;//Usernav.tsx
'use client'
import { Button } from "@/UI/widgets/button"
import { signOut } from "next-auth/react"
const UserNav = () => {
return (
<Button variant="destructive" onClick={() => signOut({
redirect: true,
callbackUrl: `${window.location.origin}/login`
})}>
Sign Out
</Button>
)
}
export default UserNavHere's my whole github repo for reference:
https://github.com/sanjana-bhat-2002/wordle-clone
Errors im getting: https://srcb.in/jLPnmaPUsW
I have not included the client component (UserNav) directly, based on the suggestion of this video:https://youtu.be/bicCg4GxOP8?si=VXAsNTynCbO8cMeM&t=3556
Answered by B33fb0n3
yea, mark only the ones as client component, that really need to be a client component. Another good way of thinking if a component should be client or not: does this component have any interactivity? Like button clicks, like state updates, like ... then mark it as
use client35 Replies
@Selkirk Rex So I'm trying to implement a simple credentials authentication with next-auth, and I'm having trouble rendering a button on my navbar as 'Sign in' or 'Sign out' based on whether the use is logged out or not.
Here's my code:
tsx
//Navbar.tsx
import Link from 'next/link';
import { buttonVariants } from '@/UI/widgets/button';
import { HandMetal } from 'lucide-react';
import UserNav from './UserNav';
import { getServerSession } from 'next-auth';
import { authOptions } from '@/lib/auth';
const Navbar = async () => {
const session = await getServerSession(authOptions);
return (
<div className='bg-zinc-900 py-2 border-b border-s-zinc-200 fixed w-full z-10 top-0'>
<div className='container flex items-center justify-between'>
<Link href='/'>
<HandMetal />
</Link>
{session?.user ? (
<UserNav />
) : (
<Link className={buttonVariants()} href='/login'>
Sign in
</Link>
)}
</div>
</div>
);
};
export default Navbar;
tsx
//Usernav.tsx
'use client'
import { Button } from "@/UI/widgets/button"
import { signOut } from "next-auth/react"
const UserNav = () => {
return (
<Button variant="destructive" onClick={() => signOut({
redirect: true,
callbackUrl: `${window.location.origin}/login`
})}>
Sign Out
</Button>
)
}
export default UserNav
Here's my whole github repo for reference:
https://github.com/sanjana-bhat-2002/wordle-clone
Errors im getting: https://srcb.in/jLPnmaPUsW
I have not included the client component (UserNav) directly, based on the suggestion of this video:https://youtu.be/bicCg4GxOP8?si=VXAsNTynCbO8cMeM&t=3556
it looks like your Navbar is a client component. Maybe not directly marked inside Navbar.tsx, but maybe a parent of it is clientside. Facts are: the Navbar is a client component. So you need to get your session using
const session = useSession()Your Navbar is handled clientside, because you marked your parent as
use client: https://github.com/sanjana-bhat-2002/wordle-clone/blob/main/src/app/page.tsx#L1@B33fb0n3 Your Navbar is handled clientside, because you marked your parent as use client: https://github.com/sanjana-bhat-2002/wordle-clone/blob/main/src/app/page.tsx#L1
Selkirk RexOP
oohhh i didn't realize why i did that
I'm actually having trouble with understanding when and why I should mark components as client side
could you help me out?
@Selkirk Rex I'm actually having trouble with understanding when and why I should mark components as client side
you should mark component as client component only when they need to be clientside. For example when they are using something with
use. So mark them as use client, when they **use**State or useEffect or useSession or ... There are so much more use cases, but that's mostly the caseSelkirk RexOP
ohhh
as you can see there is no
useXY in it, so there is no need for marking it as client componentSelkirk RexOP
ok, so i should preferably mark each individual component rather than marking parents?
yea kinda makes sense
@Selkirk Rex ok, so i should preferably mark each individual component rather than marking parents?
yea, mark only the ones as client component, that really need to be a client component. Another good way of thinking if a component should be client or not: does this component have any interactivity? Like button clicks, like state updates, like ... then mark it as
use clientAnswer
@B33fb0n3 as you can see there is no useXY in it, so there is no need for marking it as client component
as you can see: there is no interactivity in this
page.tsx. So there is no need to mark it as use client@B33fb0n3 as you can see: there is no interactivity in this page.tsx. So there is no need to mark it as use client
Selkirk RexOP
yes got it, thank you 👍
@B33fb0n3 ok that fixed the errors i had, but once i log in, the button doesn't change to 'Sign Out'
UserNav and Navbar code are the same as sent above
it changes to sign out only once i manually refresh the page 🤔
I've included this though: https://github.com/sanjana-bhat-2002/wordle-clone/blob/main/src/UI/components/LoginForm.tsx#L47
Selkirk RexOP
ok nvm ig i had to put it below router.push()
@Selkirk Rex yes got it, thank you 👍
Sure thing
@B33fb0n3 Sure thing
Selkirk RexOP
also i had another doubt, here im calling getServerSession() in my navbar component, what if i need the session across my whole app i.e. many components? passing as props seems tedious for each and every relevant component
@Selkirk Rex also i had another doubt, here im calling getServerSession() in my navbar component, what if i need the session across my whole app i.e. many components? passing as props seems tedious for each and every relevant component
you would fetch it again, when you need to use it also in a other component
@B33fb0n3 you would fetch it again, when you need to use it also in a other component
Selkirk RexOP
isn't that tedious, to fetch it everytime?
@Selkirk Rex isn't that tedious, to fetch it everytime?
you normally use the same function to fetch it, so it should be easy for you. Also if you using jwt based auth, there are no additional data source calls, so it's fine too
@B33fb0n3 you normally use the same function to fetch it, so it should be easy for you. Also if you using jwt based auth, there are no additional data source calls, so it's fine too
Selkirk RexOP
yea im using next auth and jwt, so if i call the function ONCE anywhere significant, it means that my session would be accesible across my whole site?
@Selkirk Rex yea im using next auth and jwt, so if i call the function ONCE anywhere significant, it means that my session would be accesible across my whole site?
you can use the function
getServerSession(authOptions) on serverside where you need it, yea@B33fb0n3 you can use the function getServerSession(authOptions) on serverside where you need it, yea
Selkirk RexOP
yea so that's my question, WHERE i need it implies that i gotta call the function seperately in each component? im sorry if i misunderstood you there
@Selkirk Rex yea so that's my question, WHERE i need it implies that i gotta call the function seperately in each component? im sorry if i misunderstood you there
yea, you would need to call this function in every serverside component, where you want to have this session data
@Selkirk Rex aah okay thanks
happy to help ^^
@B33fb0n3 happy to help ^^
Selkirk RexOP
hey, i'm having some trouble with getting session details on one of my components
im not able to use
getServerSession() on my SuccessModal component, and when i use it as a client component im not able to use useSession() as wellhttps://github.com/sanjana-bhat-2002/wordle-clone/blob/main/src/UI/components/SuccessModal.tsx
im able to do
but when i try making the modal a client component and use it, it appears without trigger on my gameboard, which i don't want
im able to do
useSession() on my gameboard component though: https://github.com/sanjana-bhat-2002/wordle-clone/blob/main/src/UI/components/GameBoard.tsxbut when i try making the modal a client component and use it, it appears without trigger on my gameboard, which i don't want
Selkirk RexOP
i tried this on my modal:
//'use client'
import { authOptions } from '@/lib/auth';
import { getServerSession } from 'next-auth/next';
import React from 'react'
import { useSession } from 'next-auth/react'
interface ModalProps {
show: boolean;
onClose: () => void;
children: React.ReactNode;
}
const SuccessModal = ({ show, onClose, children }: ModalProps) => {
let session;
const fetchDetails = async () => {
session = await getServerSession(authOptions);
}
if(show) {
fetchDetails();
}
console.log(`session on modal: ${session}`)
return (
<div className="fixed inset-0 flex items-center justify-center bg-black bg-opacity-50">
<div className="bg-white p-4 rounded shadow-lg">
{children}
<button onClick={onClose} className="mt-4 bg-blue-500 text-white px-4 py-2 rounded">
Close
</button>
</div>
</div>
)
}
export default SuccessModal;and im getting this: