简体   繁体   English

使用 firebase 身份验证刷新页面时如何让用户保持登录状态

[英]How do I keep a user Logged in when refreshing a page with firebase authentication

Basically, I have a page that uses the user uid in a useEffect, but when I refresh the page the user is null and thus unable to get the uid on time.基本上,我有一个在 useEffect 中使用用户 uid 的页面,但是当我刷新页面时,用户是 null,因此无法按时获取 uid。

UserAuthContext code - this is where I do my login, signup and logout UserAuthContext 代码 - 这是我登录、注册和注销的地方

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

const userAuthContext = createContext();


export function UserAuthContextProvider({children}){
    const [user, setUser] = useState(null);
    const [userInfo, setUserInfo] = useState(null);
    const auth = getAuth();

    function signUp(email, password, isAdmin){
        return createUserWithEmailAndPassword(auth, email, password);

    }

    function signIn(email, password){
            return signInWithEmailAndPassword(auth, email, password);

        
    }

    function SignOut(){
        signOut(auth).then(() => {
        // Sign-out successful.
        console.log("Sign-out successful");
        setUser(null);
        setUserInfo(null);

        }).catch((error) => {
        // An error happened.
        });
    }

    useEffect(
        () => {
          const unsubscribe = onAuthStateChanged(auth, (currentUser) =>{
                setUser(currentUser);
                
           });
           return unsubscribe();
        },
        []
    );

    return <userAuthContext.Provider value={{user, userInfo, signUp, signIn, SignOut, setUser, setUserInfo}}>{children}</userAuthContext.Provider>
}

export function useUserAuth() {
    return useContext(userAuthContext);
}

This is the page that needs the uid - user becomes null everytime I refresh the page这是需要 uid 的页面 - 每次我刷新页面时,用户都会变成 null

import Head from 'next/head'
import Navbar from '../../components/Navbar'
import Footer from '../../components/Footer';
import Link from 'next/link';
import Module from '../../components/Module';
import { addAssessment, addModule, modalState } from '../../atoms/modalAtom';
import { useRecoilState } from 'recoil';
import MyModal from '../../components/Modal';
import { collection, doc, getDoc, onSnapshot, query } from 'firebase/firestore';
import { db } from '../../firebase';
import { useEffect, useState } from 'react';
import { useUserAuth } from '../../context/UserAuthContext';
import DashboardSidebar from '../../components/DashboardSidebar';


export default function modules() {
  const [isOpen, setIsOpen] = useRecoilState(modalState);
  const [isAddModule, setIsAddModule] = useRecoilState(addModule);
  const [isAddAssessment, setIsAddAssessment] = useRecoilState(addAssessment);
  const [modules, setModules] = useState([]);
  const {user, userInfo, setUser, setUserInfo} = useUserAuth();
  // var modules = [];

  // get modules form firebase  

  useEffect(
    () => 
    onSnapshot(
      query(doc(db, "users", user.uid)),
      (userSnapshot) => {
        const userModules = userSnapshot.data().modules;
        setUserInfo(userSnapshot.data());
        if(userSnapshot.data().isAdmin){
          onSnapshot(
            query(collection(db, 'modules')),
            (snapshot) => {
              setModules(snapshot.docs);
            }
          )
        }else{
          userModules.forEach(userModule => {
            getDoc(doc(db, 'modules', userModule)).then(moduleDoc => {
                setModules(modules => [...modules, moduleDoc]);
            });
  
          });
        }

        

      }
    ),
    [db]
  )

  return (
    <div className="h-full">
      <Head>
        <title>My Uni Work</title>
        <meta name="description" content="Generated by create next app" />
        <link rel="icon" href="/favicon.ico" />
      </Head>

      <Navbar />
      <div className="lg:flex space-x-0 h-full">
          {/* sidebar area  */}
          <div>
          <DashboardSidebar modules />
          </div>
          

          {/* content area */}
          <div className="flex flex-col lg:px-10 mt-4 space-y-2 mb-6 w-full">
              <div className="lg:flex m-2 items-center justify-between">
                <p className="text-lg lg:text-2xl m-2 font-semibold text-[#333]">
                    Selected Modules     
                </p>
                 {userInfo?.isAdmin && (
                    <div className="flex flex-col lg:flex-row lg:items-center justify-end gap-1">
                    <button className="bg-[#103A5C] text-white font-semibold p-3 rounded-md hover:opacity-90
                        " onClick={(e) =>{
                          setIsOpen(true);
                          setIsAddModule(true);
                        }} >
                        Add Module
                    </button> 
                    <button className="bg-[#103A5C] text-white font-semibold p-3 rounded-md hover:opacity-90
                        " onClick={(e) =>{
                          setIsOpen(true);
                          setIsAddAssessment(true);
                        }} >
                        Add assessment
                    </button> 
                    
                    </div>
                 )}
              </div>
              
              {/* <h1>{modules.length}</h1> */}

              {modules.map(module =>(
                <Module dashboardPage key={module.data().moduleCode} module={module.data()} />
              ))}
            </div>
            
        </div>
        
      {/* Modal */}
      {isOpen && <MyModal/>}

      {/* <Footer /> */}
    </div>
  )
}

Store the user in Local Storage in the browser.将用户存储在浏览器的本地存储中。

Basically, whenever you are calling setUser() , do this instead:基本上,每当您调用setUser()时,请改为执行以下操作:

localStorage.setItem('user', *the variable which has the user data to be stored*)

To remove an item:删除项目:

localStorage.removeItem('user')

To get said item in the future:要在将来获得所述项目:

localStorage.getItem('user')

If you share the code for the function signInWithEmailAndPassword() you've created I'll be able to provide further help.如果您共享您创建的 function signInWithEmailAndPassword()的代码,我将能够提供进一步的帮助。

Note: If storing a whole object, you need to deserialize it into a string first and whenever you need to use it again you need to serialize it back up.注意:如果存储一个完整的 object,则需要先将其反序列化为字符串,当需要再次使用时,需要将其序列化备份。 This is due to limitations with the Local Storage functionality.这是由于本地存储功能的限制。

Use the function JSON.stringfy(*object variable*) to deserialize.使用 function JSON.stringfy(*object variable*)进行反序列化。

Use the function JSON.parse(*object in format of string variable*) to serialize.使用 function JSON.parse(*object in format of string variable*)进行序列化。

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

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