I’m trying to create a simple registration and login system with firebase auth, but whenever I restart the site in console.log it appears that the user is saved, but the application returns him to the login page, as if he was not saved in the system.
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
SignIn.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
The home page is just a div written home, nothing much that disrupts the logic of the code.
2
Answers
Try this
That is happening due to Redirect is executed before
onAuthStateChanged
is executed and the user is set. It just uses your initial user’s value which isnull
in a useState initialization code.You can add 1 extra useState flag-variable that will indicate if auth-check code is fired at least once, and then to reuse it with redirect logic:
and
And just before the
return
section of yourApp
component add another return withOr anything else you prefer.