Next13不适用于现有的firebase身份验证上下文

nlejzf6q  于 2022-11-30  发布在  其他
关注(0)|答案(1)|浏览(197)

我正在使用next13构建一个应用程序(以利用服务器端组件),然而,由于某种原因,我现有的AuthContext无法工作。我收到以下错误:

TypeError: React.createContext is not a function

据我所知,AuthContext需要设置为'use client',因为其中使用了useStateuseEffect,但由于某种原因,应用程序不再认为createContext实际上是一个函数。
这是我的身份验证上下文:

'use client';

import { createContext, useContext, useEffect, useState } from 'react';
import { onAuthStateChanged, signOut, signInWithEmailAndPassword, createUserWithEmailAndPassword } from 'firebase/auth';
import { auth } from '../config';

const AuthContext = createContext({});

export const useAuth = () => useContext(AuthContext);

export const AuthContextProvider = ({ children }) => {
  const [user, setUser] = useState(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    const unsubscribe = onAuthStateChanged(auth, (user) => {
      setLoading(true);
      setUser(user ?? null);
      setLoading(false);
    });
    return () => unsubscribe();
  }, []);

  const login = async (email, password) => {
    await signInWithEmailAndPassword(auth, email, password);
  };

  const logout = async () => {
    setUser(null);
    await signOut(auth)
  };

  const register = async (email, password) => {
    try {
      const userCred = await createUserWithEmailAndPassword(auth, email, password);
      await userCred.user.sendEmailVerification({
        url: process.env.NEXT_PUBLIC_HOST
      });
    } catch (err) {
      return {
        errorCode,
        errorMessage
      }
    }
  };

  return (
    <AuthContext.Provider value={{ user, loading, login, logout, register }}>
      {children}
    </AuthContext.Provider>
  );
};

然后,AuthContext将用于应用程序目录中的主布局页面:

'use client';

import { CssBaseline, Container } from '@mui/material';
import { NavBar, Footer } from '../components';
import { AuthContextProvider } from '../context';
import '@fontsource/roboto/300.css';
import '@fontsource/roboto/400.css';
import '@fontsource/roboto/500.css';
import '@fontsource/roboto/700.css';

const RootLayout = ({ children }) => {
  return (
    <html lang='en'>
      <head>
        <link rel="icon" href="/favicon.ico" />
      </head>
      <body>
        <AuthContextProvider>
          <CssBaseline />
          <NavBar />
          <Container component='main' sx={{ padding: 3 }}>
            {children}
          </Container>
          <Footer />
        </AuthContextProvider>
      </body>
    </html>
  );
}

export default RootLayout;

我不确定是否需要采用不同的方法进行身份验证,也许使用next-auth包,但我不确定最好的方法是什么。
为任何帮助干杯!

cbeh67ev

cbeh67ev1#

下面是我在应用程序中使用的useContext的一个示例。

'use client'

import { createContext, useContext, useEffect, useState } from 'react'
import { getAuth, User } from 'firebase/auth'
import { initializeApp, getApps, getApp } from 'firebase/app'
import nookies from 'nookies'

const firebaseConfig = {
  ...
}

getApps().length ? getApp() : initializeApp(firebaseConfig)

const auth = getAuth()

const AuthContext = createContext<User | null>(null)

export function AuthProvider({ children }: any) {
  //
  const [user, setUser] = useState<User | null>(null)

  useEffect(() => {
    return auth.onIdTokenChanged(async (user) => {
      if (!user) {
        setUser(null)
        nookies.set(undefined, 'token', '', { path: '/' })
      } else {
        const token = await user.getIdToken()
        setUser(user)
        nookies.set(undefined, 'token', token, { path: '/' })
      }
    })
  }, [])

  useEffect(() => {
    const handle = setInterval(async () => {
      const user = auth.currentUser
      if (user) await user.getIdToken(true)
    }, 15 * 60 * 1000)

    return () => clearInterval(handle)
  }, [])

  return <AuthContext.Provider value={user}>{children}</AuthContext.Provider>
}

export const useAuth = () => {
  return useContext(AuthContext)
}

请注意,我们还强制每15分钟刷新一次令牌,并将其保存到cookie中。您可以使用新的next13 cookie包访问服务器页面中的cookie。
您还可以通过导入我们刚刚创建的useAuth钩子来获取用户。

'use client'
import useAuth from '../context/AuthProvider'

const Page = () => {
const {user} = useAuth()

// Rest of your application
}

希望能有所帮助

相关问题