skip to Main Content

app.js

import React from "react";
import { createRoot } from "react-dom/client";
import { Provider } from "react-redux";
import configureStore from "./store/configureStore";
import { startSetExpenses } from "./actions/expenses";
import 'normalize.css/normalize.css';
import './styles/styles.scss';
import AppRouter from "./routers/AppRouter";
import 'react-dates/lib/css/_datepicker.css';
import { auth } from './firebase/firebase';
import { onAuthStateChanged } from "firebase/auth";
import { useNavigate } from "react-router-dom";

const root = createRoot(document.getElementById("app"));

const navigate = useNavigate();

const store = configureStore();

const jsx = (
    <Provider store={store}>
        <AppRouter />
    </Provider>
);

const loadingComponent = <div><p>Loading...</p></div>;

root.render(loadingComponent);

store.dispatch(startSetExpenses())
.then(() => {
    root.render(jsx);
})
.catch((error) => {
    console.error("Error fetching expenses:", error);
});

onAuthStateChanged(auth, (user) => {
    if(user){
        console.log("LoggedIN");
        navigate("/dashboard");
    }else{
        console.log("LoggedOUT");
        navigate("/");
    }
})

AppRouter.js:

import React from 'react';
import LoginPage from '../components/LoginPage';
import Header from '../components/Header';
import NotFound from '../components/NotFound';
import EditExpense from '../components/EditExpense';
import AddExpense from '../components/AddExpense';
import ExpenseDashboardPage from '../components/ExpenseDashboard';
import HelpPage from '../components/HelpPage';
import { Routes, Route, BrowserRouter } from 'react-router-dom';


const AppRouter = () => (
    <BrowserRouter >
            <Header/>
            <Routes >
                <Route path="/" element={<LoginPage />} />
                <Route path="/dashboard" element={<ExpenseDashboardPage />} />
                <Route path="/create" element={<AddExpense />} />
                <Route path="/edit/:id" element={<EditExpense />} />
                <Route path="/help" element={<HelpPage />} />
                <Route path="*" element={<NotFound />} /> 
            </Routes>
    </BrowserRouter>
);

export default AppRouter;

The store.dispatch(startSetExpenses()) is to fetch the initial data from firebase. Till it gets resolved, I am rendering the loadingComponent on screen.
What I expected by using the useNavigate from react-router-dom was to navigate to the "/" path when user is not logged in, in the onAuthStateChanged, and to "/dashboard" when a user is logged in.
But it isn’t working. How do I achieve that?

2

Answers


  1. You should debug. Is onAuthStateChanged ever called? Maybe it’s not running?

    useNavigate is a hook, it must be used inside a component.

    Login or Signup to reply.
  2. You cannot call React hooks outside React components or custom React hooks. I suggest moving the useNavigate hook call and auth state change listener into AppRouter and hoisting the BrowserRouter to the index file to wrap AppRouter to provide it the routing context.

    Example:

    App:

    import React from "react";
    import { createRoot } from "react-dom/client";
    import { Provider } from "react-redux";
    import { BrowserRouter } from "react-router-dom";
    import 'react-dates/lib/css/_datepicker.css';
    import configureStore from "./store/configureStore";
    import 'normalize.css/normalize.css';
    import { startSetExpenses } from "./actions/expenses";
    import './styles/styles.scss';
    import AppRouter from "./routers/AppRouter";
    import { auth } from './firebase/firebase';
    
    const root = createRoot(document.getElementById("app"));
    
    const store = configureStore();
    
    const jsx = (
      <Provider store={store}>
        <BrowserRouter>
          <AppRouter />
        </BrowserRouter>
      </Provider>
    );
    
    const loadingComponent = <div><p>Loading...</p></div>;
    
    root.render(loadingComponent);
    
    store.dispatch(startSetExpenses())
      .then(() => {
        root.render(jsx);
      })
      .catch((error) => {
        console.error("Error fetching expenses:", error);
      });
    

    AppRouter:

    import React from 'react';
    import { Routes, Route, useNavigate } from 'react-router-dom';
    import { onAuthStateChanged } from "firebase/auth";
    import LoginPage from '../components/LoginPage';
    import Header from '../components/Header';
    import NotFound from '../components/NotFound';
    import EditExpense from '../components/EditExpense';
    import AddExpense from '../components/AddExpense';
    import ExpenseDashboardPage from '../components/ExpenseDashboard';
    import HelpPage from '../components/HelpPage';
    
    const AppRouter = () => {
      const navigate = useNavigate();
    
      React.useEffect(() => {
        const unsubscribe = onAuthStateChanged(auth, (user) => {
          if (user) {
            console.log("LoggedIN");
            navigate("/dashboard");
          } else {
            console.log("LoggedOUT");
            navigate("/");
          }
        });
    
        return unsubscribe;
      }, []);
    
      return (
        <>
          <Header />
          <Routes>
            <Route path="/" element={<LoginPage />} />
            <Route path="/dashboard" element={<ExpenseDashboardPage />} />
            <Route path="/create" element={<AddExpense />} />
            <Route path="/edit/:id" element={<EditExpense />} />
            <Route path="/help" element={<HelpPage />} />
            <Route path="*" element={<NotFound />} /> 
          </Routes>
        </>
      );
    };
    
    export default AppRouter;
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search