如何在 Firebase/React 中持久化用户数据?

How to persist user data in Firebase/React?

如何在我的应用程序中保留用户?每次我通过我的注册页面创建用户时,如果我重新加载页面 - 用户不再登录。我已经研究了官方文档的持久性但仍然不确定何时(或如何)使用持久性函数 VS . onAuthStateChange 函数。

这个注册页面只是一个简单的电子邮件、密码、确认密码表单。用户提交数据后,他们将通过 react-router-dom 重定向到仪表板页面。再一次,用户数据呈现一次,但在页面重新加载时消失了。

/注册:

import React, {useRef, useState, useEffect} from 'react'
import {Link, Navigate, useNavigate} from 'react-router-dom'

import { useAuth } from '../contexts/AuthContext'

import { auth } from '../firebase'

export default function 
Signup() {

  //Email Input
  const emailRef = useRef()
  const [email, setEmail] = useState("")
  const [emailFlag, setEmailFlag] = useState(false)

  //Password Input
  const passwordRef = useRef()
  const [password, setPassword] = useState("")
  const [passwordFlag, setPasswordFlag] = useState(false)

  //Password Confirmation Input
  const passwordConfirmRef = useRef()
  const [passwordConfirm, setPasswordConfirm] = useState("")
  const [passwordMatchFlag, setPasswordMatchFlag] = useState()
  
  //Destructure Authorization Functionality
  const { currentUser, signup } = useAuth()

  const navigate = useNavigate()
  

  useEffect(() => {

   verify()

  },[password, passwordConfirm])

  //Verify fields are passing
  const verify = () => {

    //set default flag values
    setPasswordFlag(false)
    setPasswordMatchFlag(false)

    //Verify length
    if(passwordRef.current.value.length >= 6) {
      setPasswordFlag(true)
    }
    //Verify match
    if(passwordRef.current.value === passwordConfirmRef.current.value) {
      setPasswordMatchFlag(true)
    }
  }

const handleSubmit = () => {

  //if values pass
  if(passwordFlag === true && passwordMatchFlag === true){
    
    signup(auth, email,password)
      .then(console.log('successfuly signed up'))
      .then(console.log(currentUser))
      .then(navigate('/dashboard'))
    
  }
}

  return (

    <div className="container mx-auto flex flex-col items-center p-4 bg-gray-200 gap-y-4">

      <h1 className='text-2xl'>Signup</h1>

        <h1 className='text-md'>Email</h1>
        <input type="email" placeholder='example@gmail.com' className='h-8 p-1 w-3/4 lg:w-1/2 shadow-sm' 
        value={email} onChange={(e) => setEmail(e.target.value)} ref={emailRef}></input>
        
        <h1 className='text-md'>Password</h1>
        {!passwordFlag && <p className='text-sm'>Password must be atleast 6 characters</p>}
        <input type="password" className='h-8 w-3/4 lg:w-1/2 shadow-sm' 
        value={password} onChange={(e) => setPassword(e.target.value)} ref={passwordRef}></input>
        
        <h1 className='text-md'>Confirm Password</h1>
        {!passwordMatchFlag && <p>passwords must match</p>}
        <input type="password" className='h-8 w-3/4 lg:w-1/2 shadow-sm'
        value={passwordConfirm} onChange={(e) => setPasswordConfirm(e.target.value)} ref={passwordConfirmRef}></input>

        <button onClick={handleSubmit}
        className='bg-red-200 py-1.5 w-3/4 px-4 text-center shadow-lg rounded-lg lg:w-24'>Submit</button>

    </div>    

  )
}

/AuthContext

import React, {useContext, useState, useEffect, createContext} from 'react'

import {auth} from '../firebase'
import { createUserWithEmailAndPassword, onAuthStateChanged, setPersistence } from 'firebase/auth'

const AuthContext = createContext()

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

export function AuthProvider({children}) {

    const [currentUser, setCurrentUser] = useState()

    onAuthStateChanged(auth, (user) => {
        setCurrentUser(user)
    })

    async function signup(auth, email, password){
        await createUserWithEmailAndPassword(auth, email, password)
        console.log('user created')
    }

    const value= {
        
        currentUser,
        signup
    }

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

/仪表板

import React, {useState, useEffect} from 'react'

import { useAuth } from '../contexts/AuthContext'

export default function Dashboard() {

  
  const {currentUser} = useAuth()  

  return (
    <div>{currentUser.email}</div>
  )
}

在您的 /AuthContext 中,您可以继续将 currentUser 添加到从 firebase/auth 导入的内容中,如下所示: import { createUserWithEmailAndPassword, onAuthStateChanged, setPersistence, currentUser } from 'firebase/auth'

然后在 AuthProvider 页面首次加载时加载 currentUser 。我们可以在 useEffect 中使用新导入的 currentUser 来完成此操作,如下所示:

export function AuthProvider({children}) {

    const [currentUserState, setCurrentUserState] = useState() // renamed from currentUser and setCurrentUser to avoid naming collision with currentUser import

    useEffect(() => setCurrentUser(currentUser), []); // loads the persisted firebase user on mount

    ...

通过这种方式加载用户,我们甚至可以跨页面加载检索用户数据,因为在使用 firebase/auth 时,“默认行为是即使在用户关闭浏览器后仍保留用户会话”。 docs

由于 firebase/auth 提供的功能和数据可以在任何地方访问,您可能还想考虑完全不使用 /AuthContext。您应该能够像通常使用 React Context 一样使用 firebase/auth