orbnexus
orbnexus

Reputation: 797

[next-auth]: `useSession` must be wrapped in a <SessionProvider /> error on the existing js file

I am adding the following code to my existing js file to validate the authentication and I am trying to follow the next-auth documentations but I am getting this error "[next-auth]: useSession must be wrapped in a SessionProvider"

I am using github credentials for the validations

my code: Working when browsing to the localhost:3000/auth/api/signin

[...nextauth.js]

import NextAuth from 'next-auth'
import GitHubProvider from 'next-auth/providers/github'
export default NextAuth({
    providers:[
        GitHubProvider({
            clientId: process.env.GITHUB_ID,
            clientSecret: process.env.GITHUB_SECRET,
        }),
    ],
})

I want to put the authentication to my code written in the abc/index.js

This is my code with the next-auth and this throwing this error "[next-auth]: useSession must be wrapped in a SessionProvider"

localhost:3000/abc/index.js

import React, { Component, useMemo, useState, useEffect } from 'react';
import { useSession, SessionProvider } from 'next-auth/react';
function MyApp({ Component, pageProps }) { // i have added it here since I am not using _app.js file
  return (
    <SessionProvider session={pageProps.session}>
      <Component {...pageProps} />
    </SessionProvider>
  );
}
const abc = ({ json }) => {
  const { data: session } = useSession();
  if (session) {
    return (
      <>
        Signed in as {session.user.email} <br />
        <button onClick={() => signOut()}>Sign out</button>
      </>
    );
  }
  return (
    <>
      Not signed in <br />
      <button onClick={() => signIn()}>Sign in</button>
    </>
  );
};

Upvotes: 9

Views: 46146

Answers (6)

thatmare
thatmare

Reputation: 15

If is useful for someone:

In the project I'm working we're using Per Page Layouts, so my _app.tsx was like this:

export default function CanastaAhorro({ Component, pageProps }: any) {
  // Use the layout defined at the page level, if available
  const getLayout = Component.getLayout || ((page: any) => page);
  return getLayout(
    <>
      <Script
        ...
      />
      <ToastContainer hideProgressBar position="top-right" />
      <Component {...pageProps} />
    </>,
  );
}

But adding SessionProvider there didn't work, so I added it in each layout we have (we have 3) and that's how it worked:

import Head from "next/head";
import { SessionProvider } from "next-auth/react";

export default function FrontLayout({ children }: any) {
  return (
    <>
      <SessionProvider>
        <Head>
          <title>App</title>
        </Head>
        <div className="h-screen w-screen bg-base-100">
          <div className="h-screen flex sm:items-center justify-center">
            <div className="p-6 mx-auto aspect-auto sm:aspect-[9/16] relative bg-white sm:shadow-lg sm:rounded-lg sm:h-[90vh] overflow-auto">
              {children}
            </div>
          </div>
        </div>
      </SessionProvider>
    </>
  );
}

Upvotes: 0

Sher Sanginov
Sher Sanginov

Reputation: 595

My silly mistake was that instead of passing pageProps.session to SessionProvider, i was doing this in App component:

    const { data: session, status } = useSession();
    
     <SessionProvider session={session}>
            <Component {...pageProps} />
          </SessionProvider>

Then i removed the useSession hook from app.tsx and and instead used the hook in child components. Finally, passed pageProps.session to SessionProvider like this:

Note: pageProps is passed to App component by Next.js

<SessionProvider session={pageprops.session}>
            <Component {...pageProps} />
          </SessionProvider>

Upvotes: 0

Mohammed Bekele
Mohammed Bekele

Reputation: 1255

I may be late for this but i'm gonna post this if it might be useful.

in next.js 13.4 create a layout.js file inside the route where the session is being used and wrap SessionProvider to it. it works for me.

app/posts/createPost/layout.js

"use client";
import { SessionProvider } from "next-auth/react";

export default function PostLayout({
  children, // will be a page or nested layout
}) {
  return <SessionProvider>{children}</SessionProvider>;
}

Upvotes: 2

Stanislaw Bidowaniec
Stanislaw Bidowaniec

Reputation: 161

I had similar problem when updating to Next.js 13, solution i found:

  • "use client" providers extracted to separate files,
  • layout.tsx that wraps children components with providers,
  • all pages.tsx that are used within that layout have to be a server component (without "use client")

In main layout.tsx i use Redux and NextAuth providers:

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="en">
      <body>
        <NextAuthProvider>
          <ReduxProviders>
            {children}
          </ReduxProviders>
        </NextAuthProvider>
      </body>
    </html>
  );
}

Next-Auth provider:

"use client";

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

type Props = {
  children?: React.ReactNode;
};

export const NextAuthProvider = ({ children }: Props) => {
  return <SessionProvider>{children}</SessionProvider>;
};

Redux provider:

"use client";

import store from "./store";
import { Provider } from "react-redux";

export function ReduxProviders({ children }: { children: React.ReactNode }) {
  return <Provider store={store}>{children}</Provider>;
}

Upvotes: 9

Enes G&#252;lc&#252;
Enes G&#252;lc&#252;

Reputation: 75

Solution!

In next.js v13, I used the { SessionProvider } structure by wrapping it in the main layout structure.

layout.tsx:

'use client'
import '@/styles/global.css'
import 'react-toastify/dist/ReactToastify.css';
import { SessionProvider } from 'next-auth/react';
import { Session } from 'next-auth'

interface Props {
  session: Session | null
  children: React.ReactNode
}

 const RootLayout: React.FC <Props> = ({ children, session } ) => {
  return (
    <html lang="tr">

      <head />
      <body>
        {/* SessionProvider ile sarmallarız ki tüm route lara erişebilelim diye / yukarıda "use client" tanımlamayı unutma! */}
        <SessionProvider session={session}>
          {children}
        </SessionProvider>        
      </body>
    </html>
  )
}

export default RootLayout

The error I got:

error node_modules\next-auth\react\index.js (119:0) @ useSession
- error Error: [next-auth]: `useSession` must be wrapped in a <SessionProvider/>

Solution Way: Then I decided to move the "SessionProvider" structure into the main page.tsx in the app folder.

page.tsx:

'use client'
import HomeContainer from "@/containers/home/index";
import { SessionProvider } from 'next-auth/react';
import { Session } from 'next-auth'

interface Props {
  session: Session | null
}

const Home: React.FC<Props> = ({ session } ) => {
  return (
    <>
    {/* SessionProvider ile sarmallarız ki tüm route lara erişebilelim diye / yukarıda "use client" tanımlamayı unutma! */}
    <SessionProvider session={session}>
      <HomeContainer />
    </SessionProvider>
    </>
  );
};

export default Home;

And so I solved the error.

The final version of the layout page is below:

import '@/styles/global.css'
import 'react-toastify/dist/ReactToastify.css';

interface Props {
  children: React.ReactNode
}

 const RootLayout: React.FC <Props> = ({ children } ) => {
  return (
    
    <html lang="tr">

      <head />
      <body>
          {children}
      </body>
    </html>
  )
}

export default RootLayout

Upvotes: 5

lpizzinidev
lpizzinidev

Reputation: 13289

Make sure to wrap your app with the SessionProvider component in the _app.js file:

import { SessionProvider } from 'next-auth/react';

function MyApp({ Component, pageProps }) {
    return (
      <SessionProvider session={pageProps.session}>
        <Component {...pageProps} />
      </SessionProvider>
    );
  }

export default MyApp;

More info about _app.js in the Next.js docs.

Upvotes: 14

Related Questions