I am working on firebase authentication. I have made login, logout(on home), home pages. All are working fine. But when I try to login after I have changed something in router or in my code it works perfectly, that is redirects to Home. But when I login after logout, It does not work and reloads the same login page.
Also when isLoggedIn is set true after first try, it reloads login component. When I manually change url to /home
then it works fine.
Here is my code.
App js
import Signup from "./Signup";
import Login from "./Login";
import { BrowserRouter, Routes, Route } from "react-router-dom";
import Home from "./Home";
import ProtectedRoutes from "../ProtectedRoutes";
export default function App() {
return (
<BrowserRouter>
<Routes>
<Route path="/">
<Route
path="home"
element={
<ProtectedRoutes
isLoggedIn={JSON.parse(localStorage.getItem("isLoggedIn"))}
>
<Home />
</ProtectedRoutes>
}
/>
<Route path="login" element={<Login />} />
<Route path="signup" element={<Signup />} />
</Route>
</Routes>
</BrowserRouter>
);
}
Login
import React from "react";
import { useRef, useState } from "react";
import { Button, Card, Form, Alert, Container } from "react-bootstrap";
import { signInWithEmailAndPassword } from "firebase/auth";
import { auth } from "../firebaserc";
import { Link, useNavigate } from "react-router-dom";
export default function Login() {
const emailRef = useRef();
const passwordRef = useRef();
const [error, setError] = useState("");
const [loading, setLoading] = useState(false);
const navigate = useNavigate();
const handleSubmit = (e) => {
e.preventDefault();
signInWithEmailAndPassword(
auth,
emailRef.current.value,
passwordRef.current.value
)
.then((userCredential) => {
// Signed in
const user = userCredential.user;
// ...
console.log(user);
localStorage.setItem("isLoggedIn", true);
if (JSON.parse(localStorage.getItem("isLoggedIn"))) {
navigate("/home");
}
setError("");
})
.catch((error) => {
setError(error.message);
});
};
return (
<>
<Container
className="d-flex align-items-center justify-content-center"
style={{
minHeight: "100vh",
}}
>
<div
className="w-100"
style={{
maxWidth: "400px",
}}
>
<Card>
<Card.Body>
<h2 className="text-center mb-3">Login</h2>
{error && <Alert variant="danger">{error}</Alert>}
<Form onSubmit={handleSubmit}>
<Form.Group id="email" className="mb-2">
<Form.Label>Email</Form.Label>
<Form.Control type="email" ref={emailRef} required />
</Form.Group>
<Form.Group id="password" className="mb-2">
<Form.Label>Password</Form.Label>
<Form.Control type="password" ref={passwordRef} required />
</Form.Group>
<Button disabled={loading} className="w-100 mt-2" type="submit">
Login
</Button>
</Form>
</Card.Body>
</Card>
<div className="w-100 text-center mt-2">
New here? <Link to="/signup">Signup</Link>
</div>
</div>
</Container>
</>
);
}
Signup
import React from "react";
import { useRef, useState } from "react";
import { Button, Card, Form, Alert, Container } from "react-bootstrap";
import { createUserWithEmailAndPassword } from "firebase/auth";
import { auth } from "../firebaserc";
import { Link, useNavigate } from "react-router-dom";
export default function Signup() {
const emailRef = useRef();
const passwordRef = useRef();
const [error, setError] = useState("");
const [loading, setLoading] = useState(false);
const navigate = useNavigate();
const handleSubmit = (e) => {
e.preventDefault();
createUserWithEmailAndPassword(
auth,
emailRef.current.value,
passwordRef.current.value
)
.then((userCredential) => {
// Signed in
const user = userCredential.user;
console.log(user);
setError("");
navigate("/home");
localStorage.setItem("isLoggedIn", true);
// ...
})
.catch((error) => {
setError(error.message);
// ..
});
};
return (
<>
<Container
className="d-flex align-items-center justify-content-center"
style={{
minHeight: "100vh",
}}
>
<div
className="w-100"
style={{
maxWidth: "400px",
}}
>
<Card>
<Card.Body>
<h2 className="text-center mb-3"> Sign Up</h2>
{error && <Alert variant="danger">{error}</Alert>}
<Form onSubmit={handleSubmit}>
<Form.Group id="email" className="mb-2">
<Form.Label>Email</Form.Label>
<Form.Control type="email" ref={emailRef} required />
</Form.Group>
<Form.Group id="password" className="mb-2">
<Form.Label>Password</Form.Label>
<Form.Control type="password" ref={passwordRef} required />
</Form.Group>
<Button disabled={loading} className="w-100 mt-2" type="submit">
Sign Up
</Button>
</Form>
</Card.Body>
</Card>
<div className="w-100 text-center mt-2">
Already have an account <Link to="/login">Login</Link>
</div>
</div>
</Container>
</>
);
}
Home
import React from "react";
import { Button } from "react-bootstrap";
import { auth } from "../firebaserc";
import { signOut } from "firebase/auth";
import { useNavigate } from "react-router-dom";
export default function Home() {
const navigate = useNavigate();
const handleLogout = () => {
signOut(auth)
.then(() => {
// Sign-out successful.
localStorage.removeItem("isLoggedIn");
navigate("/login", { replace: true });
})
.catch((error) => {
// An error happened.
console.log(error.message);
});
};
return (
<div>
Home
<Button onClick={handleLogout}>Logout</Button>
</div>
);
}
Protected Routes
import { Navigate } from "react-router-dom";
const ProtectedRoutes = ({ isLoggedIn, children }) => {
if (!isLoggedIn) {
return <Navigate to="/login" replace />;
}
return children;
};
export default ProtectedRoutes;
CodePudding user response:
Let's say you want to make a React App refresh , Simply
React.useEffect(() => {
doSomething();
}, [doSomething, IsAuthenticated ]);
once this values change it will update this component
This value need to be observable
firebase gives you that
firebase.auth().onAuthStateChanged(function(user) {
if (user) {
// User is signed in.
} else {
// No user is signed in.
}
});
https://firebase.google.com/docs/auth/web/manage-users
and with react you can also make
firebase.auth().onAuthStateChanged((user) => {
if (user) {
handleLogin(user);
} else {
Logout();
}
});
function Logout() {
setAuthintecated(false)
};
Also here some resource for you
https://www.freecodecamp.org/news/react-firebase-authentication-and-crud-operations/
GoodLuck