Search code examples
reactjsnext.jsnext-auth

Server 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


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,
    },
  }
}

Solution

  • 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.

    Hover over function declaration in VSCode