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