使用 firebase 和 React js 进行身份验证时出错

问题描述 投票:0回答:2

我正在尝试使用 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,没有什么破坏代码逻辑的地方。

javascript reactjs firebase
2个回答
0
投票

试试这个

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>  
  )  

0
投票

发生这种情况是因为在执行

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>

或者您喜欢的其他任何东西。

© www.soinside.com 2019 - 2024. All rights reserved.