开发者问题收集

Nextjs next-auth sessionProvider 未读取会话属性 Typescript

2022-09-02
6178

我正在使用带有 Next-auth 的 mantine 模板,并尝试在应用程序中实现 sessionProvider,但出现错误“session is not defined”

在 session provider 上实现 session 时出错

----编辑---- 仅在 sessionProvider 上使用 session 时的错误代码

error - pages\_app.tsx (33:38) @ App
error - ReferenceError: session is not defined
    at App (webpack-internal:///./pages/_app.tsx:85:38)
    at renderWithHooks (C:\Users\alfon\Documents\GitHub\Matrix_Family\node_modules\react-dom\cjs\react-dom-server.browser.development.js:5658:16)
    at renderIndeterminateComponent (C:\Users\alfon\Documents\GitHub\Matrix_Family\node_modules\react-dom\cjs\react-dom-server.browser.development.js:5731:15)
    at renderElement (C:\Users\alfon\Documents\GitHub\Matrix_Family\node_modules\react-dom\cjs\react-dom-server.browser.development.js:5946:7)
    at renderNodeDestructiveImpl (C:\Users\alfon\Documents\GitHub\Matrix_Family\node_modules\react-dom\cjs\react-dom-server.browser.development.js:6104:11)
    at renderNodeDestructive (C:\Users\alfon\Documents\GitHub\Matrix_Family\node_modules\react-dom\cjs\react-dom-server.browser.development.js:6076:14)
    at renderIndeterminateComponent (C:\Users\alfon\Documents\GitHub\Matrix_Family\node_modules\react-dom\cjs\react-dom-server.browser.development.js:5785:7)
    at renderElement (C:\Users\alfon\Documents\GitHub\Matrix_Family\node_modules\react-dom\cjs\react-dom-server.browser.development.js:5946:7)
    at renderNodeDestructiveImpl (C:\Users\alfon\Documents\GitHub\Matrix_Family\node_modules\react-dom\cjs\react-dom-server.browser.development.js:6104:11)
    at renderNodeDestructive (C:\Users\alfon\Documents\GitHub\Matrix_Family\node_modules\react-dom\cjs\react-dom-server.browser.development.js:6076:14) {
  page: '/protegido'
}
  31 |         <MantineProvider theme={{ colorScheme }} withGlobalStyles withNormalizeCSS>
  32 |           <NotificationsProvider>
> 33 |             <SessionProvider session={session}>
     |                                      ^
  34 |               <ApolloProvider client={client}>
  35 |                 <Component {...pageProps} />
  36 |               </ApolloProvider>

我像这样将其导入到我的 _app.tsx 中

import { GetServerSidePropsContext } from 'next';
import { useState } from 'react';
import { AppProps } from 'next/app';
import { getCookie, setCookie } from 'cookies-next';
import Head from 'next/head';
import { MantineProvider, ColorScheme, ColorSchemeProvider } from '@mantine/core';
import { NotificationsProvider } from '@mantine/notifications';
import { SessionProvider } from 'next-auth/react';
import { ApolloProvider } from '@apollo/client';
import client from '../apollo-client';

export default function App(props: AppProps & { colorScheme: ColorScheme }) {
  const { Component, pageProps } = props;
  const [colorScheme, setColorScheme] = useState<ColorScheme>(props.colorScheme);

  const toggleColorScheme = (value?: ColorScheme) => {
    const nextColorScheme = value || (colorScheme === 'dark' ? 'light' : 'dark');
    setColorScheme(nextColorScheme);
    setCookie('mantine-color-scheme', nextColorScheme, { maxAge: 60 * 60 * 24 * 30 });
  };

  return (
    <>
      <Head>
        <title>Family 5 Dashboard</title>
        <meta name="viewport" content="minimum-scale=1, initial-scale=1, width=device-width" />
        <link rel="shortcut icon" href="/icono.png" />
      </Head>

      <ColorSchemeProvider colorScheme={colorScheme} toggleColorScheme={toggleColorScheme}>
        <MantineProvider theme={{ colorScheme }} withGlobalStyles withNormalizeCSS>
          <NotificationsProvider>
            <SessionProvider session={session}>
              <ApolloProvider client={client}>
                <Component {...pageProps} />
              </ApolloProvider>
            </SessionProvider>
          </NotificationsProvider>
        </MantineProvider>
      </ColorSchemeProvider>
    </>
  );
}

App.getInitialProps = ({ ctx }: { ctx: GetServerSidePropsContext }) => ({
  colorScheme: getCookie('mantine-color-scheme', ctx) || 'dark',
});

如果我使用 pageProps.session,我会收到相同的错误

session provider error

----编辑---- 仅在 pageProps.session 上使用sessionProvider

error - pages\_app.tsx (33:48) @ App
error - TypeError: Cannot read properties of undefined (reading 'session')
    at App (webpack-internal:///./pages/_app.tsx:85:48)
    at renderWithHooks (C:\Users\alfon\Documents\GitHub\Matrix_Family\node_modules\react-dom\cjs\react-dom-server.browser.development.js:5658:16)
    at renderIndeterminateComponent (C:\Users\alfon\Documents\GitHub\Matrix_Family\node_modules\react-dom\cjs\react-dom-server.browser.development.js:5731:15)
    at renderElement (C:\Users\alfon\Documents\GitHub\Matrix_Family\node_modules\react-dom\cjs\react-dom-server.browser.development.js:5946:7)
    at renderNodeDestructiveImpl (C:\Users\alfon\Documents\GitHub\Matrix_Family\node_modules\react-dom\cjs\react-dom-server.browser.development.js:6104:11)
    at renderNodeDestructive (C:\Users\alfon\Documents\GitHub\Matrix_Family\node_modules\react-dom\cjs\react-dom-server.browser.development.js:6076:14)
    at renderIndeterminateComponent (C:\Users\alfon\Documents\GitHub\Matrix_Family\node_modules\react-dom\cjs\react-dom-server.browser.development.js:5785:7)
    at renderElement (C:\Users\alfon\Documents\GitHub\Matrix_Family\node_modules\react-dom\cjs\react-dom-server.browser.development.js:5946:7)
    at renderNodeDestructiveImpl (C:\Users\alfon\Documents\GitHub\Matrix_Family\node_modules\react-dom\cjs\react-dom-server.browser.development.js:6104:11)
    at renderNodeDestructive (C:\Users\alfon\Documents\GitHub\Matrix_Family\node_modules\react-dom\cjs\react-dom-server.browser.development.js:6076:14) {
  page: '/protegido'
}
  31 |         <MantineProvider theme={{ colorScheme }} withGlobalStyles withNormalizeCSS>
  32 |           <NotificationsProvider>
> 33 |             <SessionProvider session={pageProps.session}>
     |                                                ^
  34 |               <ApolloProvider client={client}>
  35 |                 <Component {...pageProps} />
  36 |               </ApolloProvider>

---现在使用 [...nextauth] 文件编辑-----

我的 /api/auth/[...nextauth].js

import NextAuth from "next-auth"
import { ApolloClient, InMemoryCache } from "@apollo/client";
import CredentialsProvider from "next-auth/providers/credentials";
import { GET_ADMIN_LOGIN } from "../../../components/fam.querys";

export default NextAuth({

    providers: [
        CredentialsProvider({
            session: {
                strategy: 'jwt',
                maxAge: 30 * 24 * 60 * 60, //30 days
                updateAge: 24 * 60 * 60, // 24 hours
            },
            // The name to display on the sign in form (e.g. "Sign in with...")
            name: "Credentials",
            // e.g. domain, username, password, 2FA token, etc.
            credentials: {
                email: { label: "email", type: "email", placeholder: "correo" },
                password: { label: "Password", type: "password", placeholder: 'clave' }
            },
            async authorize(credentials, req) {
                // Add logic here to look up the user from the credentials supplied

                const client = new ApolloClient({
                    uri: "myUri",
                    cache: new InMemoryCache(),
                    headers: {
                        'content-type': 'application/json',
                        'x-hasura-admin-secret': '*******'
                    }
                })

                //buscar en la base de datos si existe el usuario

                /* try {
                    await client.resetStore();
                    const { data } = await client.query({
                        query: GET_ADMIN_LOGIN,
                    });

                    const adminPass = data?.control_admin[0]?.clave
                    const adminId = data?.control_admin[0]?.id
                    const adminCorr = data?.control_admin[0]?.correoadmin
                    const adminName = data?.control_admin[0]?.correoadmin

                    if (credentials.email === adminCorr && credentials.password === adminPass) {
                        return {
                            user: {
                                id: 311,
                                image: adminId,
                                name: adminName,
                                email: adminCorr,
                                tipo: 'admin'
                            },
                        }
                    }
                    return null;
                } catch (error) {
                    console.log(error)
                } */

                if (credentials.email !== '[email protected]' || credentials.password !== '1234') {
                    return null;
                }
                // si todo esta bien
                return { id: '1234', name: 'john', email: '[email protected]', tipo: 'extra' };
            }
        })
    ],

    callbacks: {
        session: async ({ session, token }) => {
            if (session?.user) {
                session.user.id = token.uid;
                session.user.tipo = token.tipo;
            }
            console.log('sesion: ', session)

            return session;
        },
        jwt: async ({ user, token }) => {
            if (user) {
                token.uid = user.id;
                token.tipo = user.tipo;
            }
            console.log('token: ', token)
            console.log('user: ', user)
            return token;
        },
    },
    pages: {
        signIn: '/',
    },
});

根据 Yilmaz 的建议,我制作了一个 ts 文件,如下所示

import {
  Session
} from 'next-auth';
import {
  JWT
} from 'next-auth/jwt';

declare module 'next-auth' {
  interface Session {
    // what ever properties added, add type here
    expires: string;
    user: {
      email: string;
      id: number;
      name: string;
      tipo: string;
    };
  }
}

然后在 _app 文件上再次尝试

import { GetServerSidePropsContext } from 'next';
import { useState } from 'react';
import { AppProps } from 'next/app';
import { getCookie, setCookie } from 'cookies-next';
import Head from 'next/head';
import { MantineProvider, ColorScheme, ColorSchemeProvider } from '@mantine/core';
import { NotificationsProvider } from '@mantine/notifications';
import { SessionProvider } from 'next-auth/react';
import { ApolloProvider } from '@apollo/client';
import client from '../apollo-client';
import { Session } from 'next-auth';

export default function App(props: AppProps & { colorScheme: ColorScheme }) {
  const { Component, pageProps } = props;
  const [colorScheme, setColorScheme] = useState<ColorScheme>(props.colorScheme);

  const toggleColorScheme = (value?: ColorScheme) => {
    const nextColorScheme = value || (colorScheme === 'dark' ? 'light' : 'dark');
    setColorScheme(nextColorScheme);
    setCookie('mantine-color-scheme', nextColorScheme, { maxAge: 60 * 60 * 24 * 30 });
  };

  return (
    <>
      <Head>
        <title>Family 5 Dashboard</title>
        <meta name="viewport" content="minimum-scale=1, initial-scale=1, width=device-width" />
        <link rel="shortcut icon" href="/icono.png" />
      </Head>

      <SessionProvider session={pageProps.session}>
        <ColorSchemeProvider colorScheme={colorScheme} toggleColorScheme={toggleColorScheme}>
          <MantineProvider theme={{ colorScheme }} withGlobalStyles withNormalizeCSS>
            <NotificationsProvider>
              <ApolloProvider client={client}>
                <Component {...pageProps} />
              </ApolloProvider>
            </NotificationsProvider>
          </MantineProvider>
        </ColorSchemeProvider>
      </SessionProvider>
    </>
  );
}

App.getInitialProps = ({ ctx }: { ctx: GetServerSidePropsContext }) => ({
  colorScheme: getCookie('mantine-color-scheme', ctx) || 'dark',
});

我仍然收到此错误

TypeError: Cannot read properties of undefined (reading 'session')
    at App (webpack-internal:///./pages/_app.tsx:75:36)
    at renderWithHooks (C:\Users\alfon\Documents\GitHub\Matrix_Family\node_modules\react-dom\cjs\react-dom-server.browser.development.js:5658:16)
    at renderIndeterminateComponent (C:\Users\alfon\Documents\GitHub\Matrix_Family\node_modules\react-dom\cjs\react-dom-server.browser.development.js:5731:15)
    at renderElement (C:\Users\alfon\Documents\GitHub\Matrix_Family\node_modules\react-dom\cjs\react-dom-server.browser.development.js:5946:7)
    at renderNodeDestructiveImpl (C:\Users\alfon\Documents\GitHub\Matrix_Family\node_modules\react-dom\cjs\react-dom-server.browser.development.js:6104:11)
    at renderNodeDestructive (C:\Users\alfon\Documents\GitHub\Matrix_Family\node_modules\react-dom\cjs\react-dom-server.browser.development.js:6076:14)
    at renderIndeterminateComponent (C:\Users\alfon\Documents\GitHub\Matrix_Family\node_modules\react-dom\cjs\react-dom-server.browser.development.js:5785:7)
    at renderElement (C:\Users\alfon\Documents\GitHub\Matrix_Family\node_modules\react-dom\cjs\react-dom-server.browser.development.js:5946:7)
    at renderNodeDestructiveImpl (C:\Users\alfon\Documents\GitHub\Matrix_Family\node_modules\react-dom\cjs\react-dom-server.browser.development.js:6104:11)
    at renderNodeDestructive (C:\Users\alfon\Documents\GitHub\Matrix_Family\node_modules\react-dom\cjs\react-dom-server.browser.development.js:6076:14)
wait  - compiling /_error (client and server)...
event - compiled client and server successfully in 853 ms (1092 modules)
error - pages\_app.tsx (31:42) @ App
error - TypeError: Cannot read properties of undefined (reading 'session')
    at App (webpack-internal:///./pages/_app.tsx:75:36)
    at renderWithHooks (C:\Users\alfon\Documents\GitHub\Matrix_Family\node_modules\react-dom\cjs\react-dom-server.browser.development.js:5658:16)
    at renderIndeterminateComponent (C:\Users\alfon\Documents\GitHub\Matrix_Family\node_modules\react-dom\cjs\react-dom-server.browser.development.js:5731:15)
    at renderElement (C:\Users\alfon\Documents\GitHub\Matrix_Family\node_modules\react-dom\cjs\react-dom-server.browser.development.js:5946:7)
    at renderNodeDestructiveImpl (C:\Users\alfon\Documents\GitHub\Matrix_Family\node_modules\react-dom\cjs\react-dom-server.browser.development.js:6104:11)
    at renderNodeDestructive (C:\Users\alfon\Documents\GitHub\Matrix_Family\node_modules\react-dom\cjs\react-dom-server.browser.development.js:6076:14)
    at renderIndeterminateComponent (C:\Users\alfon\Documents\GitHub\Matrix_Family\node_modules\react-dom\cjs\react-dom-server.browser.development.js:5785:7)
    at renderElement (C:\Users\alfon\Documents\GitHub\Matrix_Family\node_modules\react-dom\cjs\react-dom-server.browser.development.js:5946:7)
    at renderNodeDestructiveImpl (C:\Users\alfon\Documents\GitHub\Matrix_Family\node_modules\react-dom\cjs\react-dom-server.browser.development.js:6104:11)
    at renderNodeDestructive (C:\Users\alfon\Documents\GitHub\Matrix_Family\node_modules\react-dom\cjs\react-dom-server.browser.development.js:6076:14) {
  page: '/'
}
  29 |       </Head>
  30 | 
> 31 |       <SessionProvider session={pageProps.session}>
     |                                          ^
  32 |         <ColorSchemeProvider colorScheme={colorScheme} toggleColorScheme={toggleColorScheme}>   
  33 |           <MantineProvider theme={{ colorScheme }} withGlobalStyles withNormalizeCSS>
  34 |             <NotificationsProvider>

如果我使用 <SessionProvider session={props.session}>

我没有收到任何错误,但没有维护会话或用户对象,如果您重新加载页面或更改选项卡,会话将丢失

制作后next.d.ts

并使用 <SessionProvider session={pageProps.session}>

出现的错误是:

TypeError: Cannot read properties of undefined (reading 'session')
    at App (webpack-internal:///./pages/_app.tsx:75:36)
    at renderWithHooks (C:\Users\alfon\Documents\GitHub\Matrix_Family\node_modules\react-dom\cjs\react-dom-server.browser.development.js:5658:16)
    at renderIndeterminateComponent (C:\Users\alfon\Documents\GitHub\Matrix_Family\node_modules\react-dom\cjs\react-dom-server.browser.development.js:5731:15)
    at renderElement (C:\Users\alfon\Documents\GitHub\Matrix_Family\node_modules\react-dom\cjs\react-d om-server.browser.development.js:5946:7)
    at renderNodeDestructiveImpl (C:\Users\alfon\Documents\GitHub\Matrix_Family\node_modules\react-dom\cjs\react-dom-server.browser.development.js:6104:11)
    at renderNodeDestructive (C:\Users\alfon\Documents\GitHub\Matrix_Family\node_modules\react-dom\cjs\react-dom-server.browser.development.js:6076:14)
    at renderIndeterminateComponent (C:\Users\alfon\Documents\GitHub\Matrix_Family\node_modules\react-dom\cjs\react-dom-server.browser.development.js:5785:7)
    at renderElement (C:\Users\alfon\Documents\GitHub\Matrix_Family\node_modules\react-dom\cjs\react-dom-server.browser.development.js:5946:7)
    at renderNodeDestructiveImpl (C:\Users\alfon\Documents\GitHub\Matrix_Family\node_modules\react-dom\cjs\react-dom-server.browser.development.js:6104:11)
    at renderNodeDestructive (C:\Users\alfon\Documents\GitHub\Matrix_Family\node_modules\react-dom\cjs\react-dom-server.browser.development.js:6076:14)
wait  - compiling /_error (client and server)...
event - compiled client and server successfully in 961 ms (1041 modules)
error - pages\_app.tsx (31:42) @ App
error - TypeError: Cannot read properties of undefined (reading 'session')
    at App (webpack-internal:///./pages/_app.tsx:75:36)
    at renderWithHooks (C:\Users\alfon\Documents\GitHub\Matrix_Family\node_modules\react-dom\cjs\react-dom-server.browser.development.js:5658:16)
    at renderIndeterminateComponent (C:\Users\alfon\Documents\GitHub\Matrix_Family\node_modules\react-dom\cjs\react-dom-server.browser.development.js:5731:15)
    at renderElement (C:\Users\alfon\Documents\GitHub\Matrix_Family\node_modules\react-dom\cjs\react-dom-server.browser.development.js:5946:7)
    at renderNodeDestructiveImpl (C:\Users\alfon\Documents\GitHub\Matrix_Family\node_modules\react-dom\cjs\react-dom-server.browser.development.js:6104:11)
    at renderNodeDestructive (C:\Users\alfon\Documents\GitHub\Matrix_Family\node_modules\react-dom\cjs\react-dom-server.browser.development.js:6076:14)
    at renderIndeterminateComponent (C:\Users\alfon\Documents\GitHub\Matrix_Family\node_modules\react-dom\cjs\react-dom-server.browser.development.js:5785:7)
    at renderElement (C:\Users\alfon\Documents\GitHub\Matrix_Family\node_modules\react-dom\cjs\react-dom-server.browser.development.js:5946:7)
    at renderNodeDestructiveImpl (C:\Users\alfon\Documents\GitHub\Matrix_Family\node_modules\react-dom\cjs\react-dom-server.browser.development.js:6104:11)
    at renderNodeDestructive (C:\Users\alfon\Documents\GitHub\Matrix_Family\node_modules\react-dom\cjs\react-dom-server.browser.development.js:6076:14) {
  page: '/'
}
  29 |       </Head>
  30 | 
> 31 |       <SessionProvider session={pageProps.session}>
     |                                          ^
  32 |         <ColorSchemeProvider colorScheme={colorScheme} toggleColorScheme={toggleColorScheme}>  
  33 |           <MantineProvider theme={{ colorScheme }} withGlobalStyles withNormalizeCSS>
  34 |             <NotificationsProvider>
2个回答

在根目录下的文件中创建 next-auth.d.ts 并添加以下内容:

import { Session } from "next-auth"
import { JWT } from "next-auth/jwt"

declare module "next-auth" {
  interface Session {
    // what ever properties added, add type here
    user: User
  }
}

同样在根目录中,创建 next.d.ts 并添加以下内容。来自文档:

import type { NextComponentType, NextPageContext } from "next"
import type { Session } from "next-auth"
import type { Router } from "next/router"

declare module "next/app" {
  type AppProps<P = Record<string, unknown>> = {
    Component: NextComponentType<NextPageContext, any, P>
    router: Router
    __N_SSG?: boolean
    __N_SSP?: boolean
    pageProps: P & {
      /** Initial session passed in from `getServerSideProps` or `getInitialProps` */
      session?: Session
    }
  }
}

这是为此 _app.tsx 设置的正常 ts

 export default function App({ Component, pageProps }: AppProps) {

但是由于您像这样定义了您的组件

export default function App(props: AppProps & { colorScheme: ColorScheme }) {

我们必须更改 next.d.ts 中的类型定义:

declare module 'next/app' {
  type AppProps<P = Record<string, unknown>> = {
    Component: NextComponentType<NextPageContext, any, P>;
    router: Router;
    __N_SSG?: boolean;
    __N_SSP?: boolean;
    session?: Session;
    pageProps: P ;
  };
}

到目前为止正在处理 typescript 设置。代码中的错误 您破坏代码的方式

const {Component,pageProps}=props

这是错误的。 应该是:

 const { Component, session, ...pageProps } = props;

...pageProps 表示传播其余的道具。 它实际上看起来像这样

 const { Component, session,firstProps,secondProps } = props;

那么您也需要将此 session 传递给组件。

   <Component {...pageProps} session={session}/>
Yilmaz
2022-09-10

修复此错误的最简单方法(也是错误的方法)是在第 33 行添加任何类型:

<SessionProvider session={(pageProps as any).session}>
Hudson Dias
2022-09-09