I am trying to create authentication system with react everything is working. I have one private route if there is no user then it redirects to login page.
This is my private route
import React from 'react'
import { Navigate} from 'react-router-dom'
import { useAuth } from '../../context/AuthContext'
export default function PrivateRoute({children}) {
const { currentUser } = useAuth()
if(!currentUser){
return <Navigate to= '/login' />
}
return children;
}
Problem is after login I get redirect to update-profile page but if I enter login link in address bar it logs out and takes user back to login page. I don't know how to deal with that.
This is my context
import React, {useContext, useEffect, useState} from 'react'
import { auth } from '../firebase-config'
const AuthContext = React.createContext()
export function useAuth(){
return useContext(AuthContext)
}
export function AuthProvider({ children }) {
const [currentUser, setCurrentUser] = useState()
const [loading, setLoading] = useState(true)
function singup(email, password){
return auth.createUserWithEmailAndPassword(email, password)
}
function login(email, password){
return auth.signInWithEmailAndPassword(email, password)
}
function logout(){
return auth.signOut()
}
function resetPassword(email){
return auth.sendPasswordResetEmail(email)
}
function updateEmail(email){
return currentUser.updateEmail(email)
}
function updatePassword(password){
return currentUser.updatePassword(password)
}
useEffect(() =>{
const unsubscribe = auth.onAuthStateChanged(user =>{
setCurrentUser(user)
setLoading(false)
})
return unsubscribe
}, [])
const value = {
currentUser,
login,
singup,
logout,
resetPassword,
updateEmail,
updatePassword
}
return (
<AuthContext.Provider value={value}>
{ !loading && children }
</AuthContext.Provider>
)
}
Since you are manually entering a URL in the address bar, when you do this it will reload the page, which reloads your app. Anything stored in state is wiped. To keep the state you'll need to persist it to longer-term storage, i.e. localStorage.
Using localStorage you can initialize the currentUser
from localStorage, and use a useEffect
hook to persist the currentUser
to localStorage.
Example:
export function AuthProvider({ children }) {
const [currentUser, setCurrentUser] = useState(
JSON.parse(localStorage.getItem("currentUser"))
);
const [loading, setLoading] = useState(true);
useEffect(() => {
localStorage.setItem("currentUser", JSON.stringify(currentUser));
}, [currentUser]);
...
useEffect(() =>{
const unsubscribe = auth.onAuthStateChanged(user => {
setCurrentUser(user);
setLoading(false);
});
return unsubscribe;
}, []);
const value = {
currentUser,
login,
singup,
logout,
resetPassword,
updateEmail,
updatePassword
};
return (
<AuthContext.Provider value={value}>
{!loading && children}
</AuthContext.Provider>
);
}
When you re-enter a link in the address bar it deletes all your saved context, if you want a simple way to save the login state, you can save the currentUser object in the localStorage(this is a very basic way, not recommended in real websites), and then when the page loads you can use useEffect to get that data from the localStorage and set currentUser to the user you save in the localStorage.