繁体   English   中英

UseContext 在 getServer 端道具 NextJS 中返回 null

[英]UseContext returns null in getServer side props NextJS

我在其他地方使用过上下文,例如登录、数据库功能等。 但是,当我尝试在自定义 api 或getServerSideProps等位置的上下文中运行函数或变量时,它会返回以下错误TypeError: Cannot read properties of null (reading 'useContext') 我正在附加我的身份验证上下文、我的上下文初始化以及返回错误的getServerSideProps函数

_app.js

import RootLayout from '../components/Layout'
import { AuthProvider } from '../configs/auth-context'
import '../styles/globals.css'

export default function App({ Component, pageProps }) {
  return (
    <AuthProvider >
      <RootLayout>
        <Component {...pageProps} />
      </RootLayout>
    </AuthProvider>
)}    

授权上下文

import React, { useContext, useState, useEffect, useRef } from 'react'
import { auth, db, provider } from './firebase-config'
import { GoogleAuthProvider, signInWithEmailAndPassword, createUserWithEmailAndPassword, signOut, onAuthStateChanged, signInWithPopup } from 'firebase/auth'
import { doc, getDoc, setDoc } from 'firebase/firestore'
import {useRouter} from 'next/router';


const AuthContext = React.createContext({currentUser: {uid: "TestUid", email:"Testeremail@email.com"}})

export function UseAuth() {
    return useContext(AuthContext)
}

export function AuthProvider({ children }) {
    const router = useRouter();

    const [currentUser, setCurrentUser] = useState({uid: "TestUid", email:"Testeremail@email.com"})
    const [loading, setLoading] = useState(true)

    async function signup(email, password) {
        createUserWithEmailAndPassword(auth, email, password)
        .then(async (result) => {
            const user = result.user;
            await userToDb(user);
            router.push('/portfolio'); 
            return user;
        }).catch((error) => {
            console.error(error);
        })
        return
    }

    async function login(email, password) {
        return signInWithEmailAndPassword(auth, email, password)
        .then(async (result) => {
            const user = result.user;
            await userToDb(user);
            router.push('/portfolio');
            return user;
        }).catch((error) => {
            console.error(error)
        })
    }

    function logout() {
        router.push('/')
        return signOut(auth)
    }

    async function googleSignIn() {
        const provider = new GoogleAuthProvider();
        signInWithPopup(auth, provider)
        .then(async (result) => {
            const credential = GoogleAuthProvider.credentialFromResult(result);
            const token = credential.accessToken;
            // The signed-in user info.
            const user = result.user;
            await userToDb(user);
            router.push('/portfolio');    
            return user
        }).catch((error) => {
            console.log(error)
            // const errorCode = error.code;
            // const errorMessage = error.message;
            // The email of the user's account used.
            // const email = error.customData.email;
            // The AuthCredential type that was used.
            // const credential = GoogleAuthProvider.credentialFromError(error);

        } )
    }

    const userToDb = async (user)  => {
        // await setDoc(doc(db, "users", user.uid), {
        //     userEmail: user.email,
        //     userID: user.uid
        // }, {merge: false})
        let currentRef = doc(db, 'users', user.uid)
        let currentUserID = user.uid;
        let currentEmail = user.email;
        await setDoc(currentRef, {
            userEmail: currentEmail,
            userID: currentUserID
        }, {merge: false})
    }

    function fixData(docs) {
        console.log("this works")
          // setDocuments(docs);
          let retMap = new Map();
          if (currentUser !== null) {
              docs?.map(function(doc) {
                  console.log(doc)
                  let tic =  doc.stockTicker
                  let data = {
                       shares: doc.shares,
                       price: doc.price,
                       type: doc.type 
                  }
                  if(!retMap.has(tic)) {
                      retMap.set(tic, [data]);
                      console.log(tic + " " + data)
                      // setMap(new Map(datamap.set(tic, {shares: shares, averagePrice: price})))
                  }
                  else {
                      let x = retMap.get(tic);
                      x.push(data);                        
                  }
                  
              })
              console.log(retMap)
              return retMap;
          }    
      }


    useEffect(() => {
        const unsubscribe = onAuthStateChanged(auth, async user => {
            setCurrentUser(user)
            setLoading(false)
        })
        return unsubscribe
    }, [])

    const value = {
        currentUser,
        login,
        signup,
        logout,
        googleSignIn,
        fixData
    }

    return (
        <AuthContext.Provider value={value}>
            {!loading && children}
        </AuthContext.Provider>
    )
}

getServerSideProps

export async function getServerSideProps() {
    let allDocs = []
    let avgDocs = []
    const {currentUser} = UseAuth()
    return {
        props: {allDocs, avgDocs}
    }
}

不知道正确答案,但是hooks应该用在组件里,hooks无一例外地用在ssr上。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM