我正在尝试使用 firebase 身份验证创建一个简单的注册和登录系统,但是每当我在 console.log 中重新启动站点时,似乎用户已保存,但应用程序将他返回到登录页面,就好像他没有保存一样已保存在系统中。
App.jsx:
import { useState, useEffect } from 'react'
import { BrowserRouter, Routes, Route, Navigate } from 'react-router-dom'
import { onAuthStateChanged } from 'firebase/auth'
import { auth } from './firebase'
// Pages
import SignUp from './pages/SignUp.jsx'
import SignIn from './pages/SignIn.jsx'
import Home from './pages/Home.jsx'
function App() {
const [authUser, setAuthUser] = useState(null)
useEffect(() => {
const listen = onAuthStateChanged(auth, (user) => {
if (user) {
setAuthUser(user)
console.log(user)
} else {
setAuthUser(null)
}
})
return () => {
listen()
}
}, [])
return (
<div>
<BrowserRouter>
<Routes>
<Route path='/' element={authUser ? <Home/> : <Navigate to='signIn'/>}/>
<Route path='/signup' element={<SignUp />} />
<Route path='/signin' element={<SignIn />} />
</Routes>
</BrowserRouter>
</div>
)
}
export default App
登录.jsx:
import { signInWithEmailAndPassword } from 'firebase/auth'
import React from 'react'
import { Link, useNavigate } from "react-router-dom"
import { useState } from 'react'
import { auth } from "../firebase.js"
const SignIn = () => {
const [email, setEmail] = useState("")
const [password, setPassword] = useState("")
const nav = useNavigate()
const handleSubmit = async (e) => {
e.preventDefault()
try {
const userCredential = await signInWithEmailAndPassword(auth, email, password)
console.log(userCredential)
nav('/')
} catch (error) {
console.log(error)
}
}
return (
<div className='min-h-[100vh] flex flex-col justify-center'>
<form className='w-[80vw] flex flex-col items-center mx-auto p-5 bg-neutral-content rounded-md' onSubmit={handleSubmit}>
<h1 className='text-2xl font-bold mb-4'>Sign-In</h1>
<label className="input input-bordered rounded flex items-center gap-2 my-3" htmlFor='email'>
<input name="email" type="email" className="grow" placeholder="Digit your email" onChange={(e) => setEmail(e.target.value)} value={email} required />
</label>
<label className="input input-bordered rounded flex items-center gap-2 my-3">
<input type="text" className="grow" placeholder="Digit your password" onChange={(e) => setPassword(e.target.value)} required value={password} />
</label>
<Link to='/signUp' className='text-sm mb-2'>Não tenho conta. <span className='underline'>Cadastrar-se</span></Link>
<input type="submit" value="Entrar" className='btn rounded mt-3' />
</form>
</div>
)
}
export default SignIn
SignUp.jsx:
import { createUserWithEmailAndPassword } from 'firebase/auth'
import React from 'react'
import { Link, useNavigate } from "react-router-dom"
import { useState } from 'react'
import { auth } from '../firebase'
const SignUp = () => {
const [email, setEmail] = useState("")
const [password, setPassword] = useState("")
const [confirmKey, setConfirmKey] = useState("")
const navigate = useNavigate()
const handleSubmit = async(e) => {
e.preventDefault()
console.log(`email: ${email} | senha: ${password} | senha dnv: ${confirmKey}`)
setEmail("")
setPassword("")
setConfirmKey("")
try {
const userCredentials = await createUserWithEmailAndPassword(auth, email, password)
console.log(userCredentials)
navigate('/')
} catch (error) {
console.log(error)
}
}
return (
<div className='min-h-[100vh] flex flex-col justify-center'>
<form className='w-[80vw] flex flex-col items-center mx-auto p-5 bg-neutral-content rounded-md' onSubmit={handleSubmit}>
<h1 className='text-2xl font-bold mb-4'>Sign-up</h1>
<label className="input input-bordered rounded flex items-center gap-2 my-3" htmlFor='email'>
<input name="email" type="email" className="grow" placeholder="Digit your email" onChange={(e) => setEmail(e.target.value)} value={email} required />
</label>
<label className="input input-bordered rounded flex items-center gap-2 my-3">
<input type="text" className="grow" placeholder="Digit your password" onChange={(e) => setPassword(e.target.value)} required value={password} />
</label>
<label className="input input-bordered rounded flex items-center gap-2 my-3">
<input type="text" className="grow" placeholder="Confirm your password" onChange={(e) => setConfirmKey(e.target.value)} required value={confirmKey} />
</label>
<Link to='/signin' className='text-sm mb-2'>Já tenho uma conta. <span className='underline'>Logar-se</span></Link>
<input type="submit" value="Cadastrar" className='btn rounded mt-3' />
</form>
</div>
)
}
export default SignUp
首页只是一个div写的home,没有什么破坏代码逻辑的地方。
试试这个
return (
<div>
<BrowserRouter>
<Routes>
<Route path='/' element={authUser !== null ? <Home/> : <Navigate to='signIn'/>}/>
<Route path='/signup' element={<SignUp />} />
<Route path='/signin' element={<SignIn />} />
</Routes>
</BrowserRouter>
</div>
)
发生这种情况是因为在执行
onAuthStateChanged
并设置用户之前执行了重定向。它只是使用您的初始用户值,即 useState 初始化代码中的 null
。
您可以添加 1 个额外的 useState 标志变量,该变量将指示是否至少触发一次身份验证检查代码,然后通过重定向逻辑重用它:
const [isAuthReady, setIsAuthReady] = useState(false);
和
useEffect(() => {
const listen = onAuthStateChanged(auth, (user) => {
if (user) {
setAuthUser(user)
console.log(user)
} else {
setAuthUser(null)
}
setIsAuthReady(true);
})
return () => {
listen()
}
}, [])
在
return
组件的 App
部分之前添加另一个带有 的返回
if (!isAuthReady) return <p>Loading...</p>
或者您喜欢的其他任何东西。