Note: using firebase v9
On my webapp, I'm trying to have it so that after a successful login we redirect the user to the main page, and if it's unsuccessful we stay on the login page.
I originally just tried using private router, but I believe the currentUser wasn't getting set by useAuth(); so it wasn't getting defined.
Then I tried using the async await method, but I got more errors.
Here is the error I get in the console log:
Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function.
at RequireAuth (http://localhost:3000/static/js/main.chunk.js:262:82)
Here is my implementation in App.js:
import { useState } from "react";
import "./App.css";
import Signup from "./pages/Signup";
import Login from "./pages/Login";
import { BrowserRouter, Routes, Route, Link, Navigate, Outlet } from "react-router-dom";
import Home from "./pages/Home";
import { useAuth } from "./firebase";
function App() {
const [mainSection, setMainSection] = useState("home");
const d = new Date();
const time = d.getHours();
if (time >= 18 || time < 5) {
document.documentElement.classList.add("dark");
}
// async function PrivateRoute({children}) {
// // setLoading(true);
// try{
// const currentUser = await useAuth();
// return currentUser ? children : <Navigate to="/login" />;
// // await login(emailRef.current.value, passwordRef.current.value);
// } catch {
// alert("Error! Authentication failed!!")
// }
// // setLoading(false);
// }
function RequireAuth() {
const currentUser = useAuth();
console.log('currentUser (private router): ', currentUser);
if (!currentUser) {
return <Navigate to="/login"/>;
}
return <Outlet />
// <Home mainSection={mainSection} setMainSection={setMainSection} />;
// return auth ? children : <Navigate to="/signup" />;
}
return (
<BrowserRouter>
<Routes>
<Route element={<RequireAuth/>}>
<Route path="/" element={<Home mainSection={mainSection} setMainSection={setMainSection} />}/>
</Route>
<Route path="/login" element={<Login />} />
<Route path="/signup" element={<Signup />} />
</Routes>
</BrowserRouter>
);
}
export default App;
And here is my implementation that holds useAuth:
// Import the functions you need from the SDKs you need
import { useEffect, useState } from "react";
import { initializeApp } from "firebase/app";
import { getAuth, createUserWithEmailAndPassword, signInWithEmailAndPassword, onAuthStateChanged } from "firebase/auth";
import { getFirestore } from "firebase/firestore";
import { doc, setDoc } from "firebase/firestore";
import { v4 as uuidv4 } from "uuid";
// TODO: Add SDKs for Firebase products that you want to use
// https://firebase.google.com/docs/web/setup#available-libraries
// Your web app's Firebase configuration
const firebaseConfig = {
apiKey: "AIzaSyBN30k6RivLOuz7KToi_uD8V5s5cmyD9RM",
authDomain: "auth-development-62c42.firebaseapp.com",
projectId: "auth-development-62c42",
storageBucket: "auth-development-62c42.appspot.com",
messagingSenderId: "414005826367",
appId: "1:414005826367:web:7b987851735426ebedf98a"
};
// Initialize Firebase
const app = initializeApp(firebaseConfig);
const auth = getAuth();
export function signup(email, password) {
return createUserWithEmailAndPassword(auth, email, password);
}
export function login(email, password) {
return signInWithEmailAndPassword(auth, email, password);
}
// eventually write a logout function
export async function sendHabitToFirestore(uidPath, habitName) {
const db = getFirestore();
const habitId = uuidv4();
const pathDocRef = doc(db, "users", uidPath, "user_habits", habitId);
//initialize habitValues for the whole year
const habitValues = []
var d = new Date();
var year = d.getFullYear();
for (let day = 1; day <= 31; day++) {
var dateString = year.toString() + '-01-' + day.toString();
var value = { date: dateString, completed: false };
habitValues.push(value);
}
await setDoc(pathDocRef, {
name: habitName,
id: habitId,
calendarData: habitValues,
});
}
export function useAuth() {
const [currentUser, setCurrentUser ] = useState();
useEffect(() => {
const unsub = onAuthStateChanged(auth, user => setCurrentUser(user));
return unsub;
}, [])
return currentUser;
}
export default getFirestore();