Si obtengo un usuario autenticado actualmente a través de auth.currentUser , ¿es esta una llamada asíncrona y se manejará como tal?
Es decir, tengo este componente de aplicación de nivel superior en reaccionar con firebase en el backend.
import { BrowserRouter, Routes, Route } from 'react-router-dom'; import MainNav from './layouts/Navbar.js'; import Homepage from './pages/Homepage'; import Login from './pages/Login'; import Register from './pages/Register'; import Profile from './pages/Profile'; import Question from './pages/Question'; import auth from 'auth/path/from/firebase-config' function App() { const user = auth.currentUser return ( <> <BrowserRouter> <MainNav /> <Routes> <Route path="/" element={<Homepage />} /> <Route path="/questions/:id" element={<Question />} /> <Route path="/users/:id" element={<Profile />} /> <Route path="/login" element={<Login />} /> <Route path="/register" element={<Register />} /> </Routes> </BrowserRouter> </> ); } export default App;Quisiera saber si hay un usuario autenticado y decírselo al . Dependiendo de si hay un usuario que quiero mostrar registro y botones de inicio de sesión o botón de cierre de sesión (o algo así)
¿Hay tal vez una manera aquí de utilizar el observador onAuthStateChanged de firebase?
Firebase restaura automáticamente las credenciales de usuario cuando la página/aplicación se vuelve a cargar. Esto requiere que haga una llamada al servidor, por lo que sucede de forma asíncrona. Es probable que esta llamada no se haya completado cuando se ejecuta su auth.currentUser , lo que significa que obtiene un null para el usuario actual.
De hecho, la solución es, como usted dice, usar un oyente de estado de autenticación, que se activa por primera vez después de que se completa la llamada asíncrona.
Sí, debe esperar a onAuthStateChanged para que esté listo. En mi aplicación, creé un componente de nivel superior para manejar este caso. Este componente bloquea el renderizado, hasta que Firebase esté listo.
import { useCallback, useEffect } from 'react' import { useDispatch, useSelector } from 'react-redux' import { fetchProfileDetails, handleAuthStateChanged } from '../../redux/actions/auth'; import { getAuth, onAuthStateChanged } from 'firebase/auth' const auth = getAuth() export default function AuthGate({ children }) { const dispatch = useDispatch() const authStatus = useSelector(state => state.auth.status) //idle (default, onAuthStateChanged not yet fired) || authenticated || unauthenticated const profileStatus = useSelector(state => state.auth.profile.query.status) //idle || loading || succeeded || failed. useEffect(() => { const unsubscribe = onAuthStateChanged(auth, user => { dispatch(handleAuthStateChanged(user)) // this line is responsible to change authStatus from `idle` to `authenticated` || `unauthenticated` }) return () => { unsubscribe() } }, [dispatch]); useEffect(() => { if (authStatus === 'authenticated') { dispatch(fetchProfileDetails()) //fetch profile details from backend each user authenticated } else { // clear profile details each logout } }, [authStatus, dispatch]); const renderChildren = useCallback(() => { if (authStatus === 'idle' || profileStatus === 'idle' || profileStatus === 'loading') { //show loading component } else if (profileStatus === 'failed') { //show error component } else { return children } }, [authStatus, children, profileStatus]) return renderChildren() }índice.js
//... ReactDOM.render( //... <AuthGate> <App /> </AuthGate> //... , document.getElementById('root') );