skip to Main Content

I’m trying to use getServerSession() in next.js like this:

import Login from "./Login";
import Logged from "./Logged";
import { getServerSession } from "next-auth";

export default async function Nav() {
  const session = await getServerSession();
  console.log(session.user);

  return (
    <nav className="flex justify-end">
      {!session?.user && <Login />}
      {session?.user && <Logged />}
    </nav>
  );
}

Login.tsx:

"use client";

import { signIn } from "next-auth/react";

export default function Login() {
  return (
    <nav className="flex justify-end">
      <button
        className="text-black cursor-pointer underline text-lg p-6 hover:text-gray-600"
        onClick={() => signIn()}
      >
        Sign In
      </button>
    </nav>
  );
}

Logged.tsx (didn’t add the functionality yet):

export default function Logged() {
  return <button>Sign out</button>;
}

However, this makes my website a blank page. If I remove the async await and the getServerSession(), it works fine. I believe the problem is with async await, but getServerSession() doesn’t work without it. I am using Typescript and the app directory.

Couldn’t find why my website just goes blank because of async await.

3

Answers


  1. From what i remember, you can’t export a default async component. Or moreover you should not directly use await getServerSession(). Either use something like getServerSideProps to execute the getServerSession and send the info with props of the pages. Or try to create a state that contain session like this :

    export default function Nav() {
      
      const [session, setSession] = useState(null)
    
      useEffect(()=>{
        const getSession = async () => {
            try{
                const res = await getServerSession();
                if (typeof res === "undefined" || !!!res)
                {
                    throw Error("Cannot get server session");
                }
                setSession(res)
            }
            catch (e) 
            {
                console.error(e)
            }
    
        }
        getSession()
      },[])
      return (
        <nav className="flex justify-end">
          {!session?.user && <Login />}
          {session?.user && <Logged />}
        </nav>
      );
    }
    

    The documentation of next-auth tell to use getServerSideProps like follow :

    import { authOptions } from 'pages/api/auth/[...nextauth]'
    import { getServerSession } from "next-auth/next"
    export default YourComponent = (props) => {
    // ...your component
    }
    export async function getServerSideProps(context) {
      const session = await getServerSession(context.req, context.res, authOptions)
    
      if (!session) {
        return {
          redirect: {
            destination: '/',
            permanent: false,
          },
        }
      }
    
      return {
        props: {
          session,
        },
      }
    }
    

    See
    https://next-auth.js.org/configuration/nextjs
    Hope it could respond your answer

    Login or Signup to reply.
  2. A component can’t be async. If you want to fetch data asynchronously in React, the core React concept you’re missing is maintaining state. Define a state value to store that data, fetch the data in an effect, and update state.

    For example:

    export default function Nav() {
      const [session, setSession] = useState();
    
      useEffect(() => {
        const fetchData = async () => {
          const result = await getServerSession();
          setSession(result);
        };
        fetchData();
      }, []);
    
      console.log(session?.user);
    
      return (
        <nav className="flex justify-end">
          {!session?.user && <Login />}
          {session?.user && <Logged />}
        </nav>
      );
    }
    
    Login or Signup to reply.
  3. A component cannot be an async function, it needs to be a React Functional Component or a React Class Component

    In order to fix the issue you are experiencing, you can call the async function inside of a useEffect when the component will mount:

    import Login from "./Login"
    import Logged from "./Logged"
    import { useEffect, useState } from "react"
    import { getServerSession } from "next-auth"
    
    export default function Nav() {
      const [user, setUser] = useState()
      useEffect(() => {
          const fetchAndSet = async () => {
              try {
                  const responseData = await getServerSession()
                  setUser(responseData.user)
              } catch (error) {
                 // Handle your errors in here
             }
         };
    
          fetchAndSet()
      }, [])
    
      return (
        <nav className="flex justify-end">
          {user ? <Logged /> : <Login />}
        </nav>
      );
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search