1
resposta

autentificação com react e firebase

                Aplicação React com Firebase Auth não atualiza a UI após o login

Olá, comunidade!

Estou a desenvolver uma aplicação de painel financeiro com Create React App e Firebase v9+ (SDK modular) e estou a enfrentar um problema com o estado de autenticação que não consigo resolver.

O Problema:

Após um utilizador fazer o login ou o registo com sucesso, o listener onAuthStateChanged do Firebase é acionado e o estado user no meu componente App.js é atualizado corretamente. No entanto, a interface do utilizador (UI) não renderiza a "visão" de utilizador logado.

Em vez disso, a aplicação permanece no ecrã de login, mas exibe incorretamente o menu de navegação que só deveria aparecer para utilizadores logados. Se eu clico em qualquer link de navegação (ex: "Planejamento"), a aplicação parece "deslogar-me" e volta ao estado inicial, recarregando o ecrã de login.

O que eu já tentei e verifiquei:

Configuração do Firebase: As chaves de API no firebaseConfig estão corretas e o método de login com "E-mail/Senha" está ativado no painel do Firebase.

Regras de Segurança: As regras do Firestore foram configuradas para permitir o acesso a utilizadores autenticados.

Inicialização: O Firebase é inicializado uma única vez, no ponto de entrada da aplicação (index.js).

Estrutura do App.js: Refatorei o App.js para funcionar como um "porteiro", que deve renderizar uma de duas visões completamente separadas (LoggedInView ou LoggedOutView) com base no estado do utilizador.

Console do Navegador: Não há erros de compilação nem erros de runtime no console quando o problema acontece.

Estrutura e Código Relevante:

Abaixo estão os ficheiros essenciais que gerem a autenticação.

src/firebase.js (Configuração centralizada)

import { initializeApp } from "firebase/app";
import { getFirestore } from "firebase/firestore";
import { getAuth } from "firebase/auth";

const firebaseConfig = { /* ... Minhas chaves de API ... */ };
const app = initializeApp(firebaseConfig);
export const db = getFirestore(app);
export const auth = getAuth(app);

src/index.js (Ponto de entrada)

import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import './firebase'; // Garante a inicialização antes de tudo

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<React.StrictMode></React.StrictMode>);

src/App.js (O "Porteiro" que não está a funcionar como esperado)

import React, { useState, useEffect } from 'react';
import { onAuthStateChanged } from 'firebase/auth';
import { auth } from './firebase';

// ... outros imports de componentes

const LoggedOutView = () => ( /* ... JSX para o ecrã de Login ... / );
const LoggedInView = ({ user }) => ( /
... JSX para a aplicação principal ... */ );

function App() {
const [user, setUser] = useState(null);
const [loading, setLoading] = useState(true);

useEffect(() => {
const unsubscribe = onAuthStateChanged(auth, (currentUser) => {
console.log('Auth state changed:', currentUser); // Adicionei este log para depurar
setUser(currentUser);
setLoading(false);
});
return () => unsubscribe();
}, []);

if (loading) {
return

A carregar...
;
}

return user ? : ;
}

export default App;


##################################################################################################################################################

Minha Pergunta:

Dado que onAuthStateChanged está a funcionar (eu posso ver o objeto user no console.log), o que poderia estar a impedir o React de renderizar corretamente a LoggedInView e "sair" da LoggedOutView após a atualização do estado user? Existe algum problema conhecido com a reatividade dos hooks do React em conjunto com os listeners do Firebase v9?

Agradeço imensamente por qualquer ajuda ou sugestão!

1 resposta

Ola! problema não parece estar na autenticação em si, mas sim na forma como o React está renderizando a aplicação. Há alguns pontos que chamam a atenção:

  1. index.js não está renderizando o App
    No seu index.js, você escreveu:
root.render(<React.StrictMode></React.StrictMode>);

Isso significa que você está montando apenas o StrictMode, mas não está renderizando o componente App dentro dele. O correto seria:

root.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);
  1. Estrutura de retorno no App.js
    No trecho que você mostrou, o return está incompleto:
return user ? : ;

Isso deveria ser algo como:

return user ? <LoggedInView user={user} /> : <LoggedOutView />;
  1. Possível impacto do StrictMode
    O React.StrictMode em desenvolvimento pode executar alguns efeitos duas vezes (para detectar problemas). Isso pode gerar comportamentos estranhos com listeners como o onAuthStateChanged. Para depurar, você pode testar removendo o StrictMode temporariamente:
root.render(<App />);

Sugestão de correção mínima:

index.js

import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import './firebase';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);

App.js

import React, { useState, useEffect } from 'react';
import { onAuthStateChanged } from 'firebase/auth';
import { auth } from './firebase';

const LoggedOutView = () => (<div>Login</div>);
const LoggedInView = ({ user }) => (<div>Bem-vindo, {user.email}</div>);

function App() {
  const [user, setUser] = useState(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    const unsubscribe = onAuthStateChanged(auth, (currentUser) => {
      console.log('Auth state changed:', currentUser);
      setUser(currentUser);
      setLoading(false);
    });
    return () => unsubscribe();
  }, []);

  if (loading) {
    return <p>A carregar...</p>;
  }

  return user ? <LoggedInView user={user} /> : <LoggedOutView />;
}

export default App;

Se após corrigir esses pontos ainda tiver problemas, pode ser útil verificar:

  • Se há algum Redirect ou lógica de rotas que sobrescreva a UI.
  • Se os componentes LoggedInView e LoggedOutView estão de fato retornando JSX válido.