I am learning Next auth. I am getting this error when i load the website:
**Server Error Error: Objects are not valid as a React child (found: [object Promise]). If you meant to render a collection of children, use an array instead.
This error happened while generating the page. Any console logs will be displayed in the terminal window.**
This is happening only when I added the auth logic in my navbar. Here's the code of Navbar component:
import { Dialog, Disclosure, Popover, Transition } from '@headlessui/react'
import {
ArrowPathIcon,
Bars3Icon,
ChartPieIcon,
CursorArrowRaysIcon,
FingerPrintIcon,
SquaresPlusIcon,
XMarkIcon,
} from '@heroicons/react/24/outline'
import { ChevronDownIcon, PhoneIcon, PlayCircleIcon } from '@heroicons/react/20/solid'
import Link from 'next/link'
import type {
GetServerSidePropsContext,
InferGetServerSidePropsType,
} from "next"
import { getProviders, signIn } from "next-auth/react"
import { getServerSession } from "next-auth/next"
import options from '../../pages/api/auth/[...nextauth]';
const products = [
{ name: 'Analytics', description: 'Get a better understanding of your traffic', href: '#', icon: ChartPieIcon },
{ name: 'Engagement', description: 'Speak directly to your customers', href: '#', icon: CursorArrowRaysIcon },
{ name: 'Security', description: 'Your customers’ data will be safe and secure', href: '#', icon: FingerPrintIcon },
{ name: 'Integrations', description: 'Connect with third-party tools', href: '#', icon: SquaresPlusIcon },
{ name: 'Automations', description: 'Build strategic funnels that will convert', href: '#', icon: ArrowPathIcon },
]
const callsToAction = [
{ name: 'Watch demo', href: '#', icon: PlayCircleIcon },
{ name: 'Contact sales', href: '#', icon: PhoneIcon },
]
function classNames(...classes:String[]) {
return classes.filter(Boolean).join(' ')
}
async function Navbar ({session}) {
return (
<header style={{backgroundColor:"#f85606"}}>
<nav className="mx-auto flex max-w-7xl items-center justify-between py-6" aria-label="Global">
<div className="flex lg:flex mr-10">
<a href="#" className="-m-1.5 p-1.5">
<span className="sr-only">Your Company</span>
<img className="h-10 w-auto" src="https://icms-image.slatic.net/images/ims-web/e650d6ca-1841-4646-b0e9-4ddbf2beb731.png" alt="" />
</a>
</div>
<Popover.Group className="hidden lg:flex">
<Popover className="relative">
<Popover.Button className="flex pt-2 items-center text-md font-semibold leading-6 text-white">
Product
<ChevronDownIcon className="h-5 w-5 flex-none text-white" aria-hidden="true" />
</Popover.Button>
<Transition
as={Fragment}
enter="transition ease-out duration-200"
enterFrom="opacity-0 translate-y-1"
enterTo="opacity-100 translate-y-0"
leave="transition ease-in duration-150"
leaveFrom="opacity-100 translate-y-0"
leaveTo="opacity-0 translate-y-1"
>
<Popover.Panel className="absolute -left-8 top-full z-10 mt-3 w-screen max-w-md overflow-hidden rounded-3xl bg-white shadow-lg ring-1 ring-gray-900/5">
<div className="p-4">
{products.map((item) => (
<div
key={item.name}
className="group relative flex items-center gap-x-6 rounded-lg p-4 text-sm leading-6 hover:bg-gray-50"
>
<div className="flex h-11 w-11 flex-none items-center justify-center rounded-lg bg-gray-50 group-hover:bg-white">
<item.icon className="h-6 w-6 text-gray-600 group-hover:text-indigo-600" aria-hidden="true" />
</div>
<div className="flex-auto">
<a href={item.href} className="block font-semibold text-gray-900">
{item.name}
<span className="absolute inset-0" />
</a>
<p className="mt-1 text-gray-600">{item.description}</p>
</div>
</div>
))}
</div>
<div className="grid grid-cols-2 divide-x divide-gray-900/5 bg-gray-50">
{callsToAction.map((item) => (
<a
key={item.name}
href={item.href}
className="flex items-center justify-center gap-x-2.5 p-3 text-sm font-semibold leading-6 text-gray-900 hover:bg-gray-100"
>
<item.icon className="h-5 w-5 flex-none text-gray-400" aria-hidden="true" />
{item.name}
</a>
))}
</div>
</Popover.Panel>
</Transition>
</Popover>
<div style={{width:"40rem"}} className="flex rounded-md shadow-sm ring-1 ring-inset ring-gray-300 focus-within:ring-2 focus-within:ring-inset focus-within:ring-indigo-600">
<input
type="text"
name="username"
id="username"
autoComplete="username"
className="block w-full flex-1 rounded-l-md border border-0 bg-white py-1.5 pl-1 text-white-900 placeholder:text-white-400 focus:outline-none sm:text-sm sm:leading-6"
placeholder="janesmith"
/>
<span className="flex select-none rounded-r-md bg-white items-center pl-3 text-orange-900 sm:text-sm">workcation.com/</span>
</div>
</Popover.Group>
<div className="hidden lg:flex lg:flex-1 lg:justify-end">
<Link href="/User" className="text-sm mx-2 font-semibold leading-6 text-gray-900">
User Home
</Link>
<Link href="/" className="text-sm mx-2 font-semibold leading-6 text-gray-900">
App Home
</Link>
<Link href="/User/Cart" className="text-sm mx-2 font-semibold leading-6 text-gray-900">
User Cart
</Link>
<Link href="/admin" className="text-sm mx-2 font-semibold leading-6 text-gray-900">
Admin
</Link>
{/* {session ? <Link href="/api/auth/signout?callback=/">Logout</Link>:
<Link href="/api/auth/signin">Login</Link>
} */}
</div>
</nav>
</header>
)
}
export default Navbar;
export async function getServerSideProps(context: GetServerSidePropsContext) {
const session = await getServerSession(context.req, context.res, options)
console.log(session)
// If the user is already logged in, redirect.
// Note: Make sure not to redirect to the same page
// To avoid an infinite loop!
if (!session) {
return {
redirect: {
destination: '/',
permanent: false,
},
}
}
return {
props: {
session,
},
}
}
Your function Navbar
is returning a promise instead of a JSX Element. When you declare your function as async
, it will always return a Promise
. To fix this, you simply need to remove async
in your function declaration, i.e.,
function Navbar({ session }) {
// your function body
}
Tip: Since you are using Typescript, if you are using VSCode, you can always hover over your function name to see what Typescript infers your function signature as.