I was able to fix it by creating a context around the app for the user.
And then changing the login server action to return the user:
export async function login(formData: FormData) {
const supabase = await createClient()
const data = {
email: formData.get('email') as string,
password: formData.get('password') as string,
}
const { data: authData, error } = await supabase.auth.signInWithPassword(data)
if (error) {
throw new Error(error.message)
}
revalidatePath('/')
return authData.session?.user || null
}
And then on the login page which is client side, update the user:
"use client"
import { login } from "./actions"
import { useRouter } from "next/navigation"
import { useUser } from "@/context/UserContext"
export default function LoginPage() {
const router = useRouter()
const { setUser } = useUser()
async function handleSubmit(formData: FormData) {
const loggedInUser = await login(formData) // Modify login to return user
if (loggedInUser) {
setUser(loggedInUser)
router.refresh() // Force the header to re-check session
router.push("/private")
} else {
// Handle login error if needed
}
}
return (
<form onSubmit={async (e) => {
e.preventDefault()
await handleSubmit(new FormData(e.currentTarget))
}}>
<label htmlFor="email">Email:</label>
<input id="email" name="email" type="email" required />
<label htmlFor="password">Password:</label>
<input id="password" name="password" type="password" required />
<button type="submit">Log in</button>
</form>
)
}