0

I'm trying to declare a boolean from my firebase.js configuration file that depends on an if-else statement that checks whether a user is logged in or not.

I want to store the log in status of a user in a boolean variable and export that variable across different components in my React app.

So if user is logged in I want my variable isLoggedIn to be true and export that. But I want the isLoggedIn boolean to be updated depending on the log-in status before it gets exported.

Here is my firebase.js file


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

const firebaseConfig = {
    //private keys
};

const app = initializeApp(firebaseConfig);
export const auth = getAuth(app);

//Problem
let isLoggedIn = false;
function checkLoggedInStatus() {
    if (auth.currentUser !== null) { //i.e. user is signed in
        isLoggedIn = true;
    }
    return isLoggedIn;
}

checkLoggedInStatus();

export isLoggedIn;

  • Where do you call `checkLoggedInStatus`? And you can't reassign a `const`, does just using `let` instead fix the problem? – CertainPerformance Jun 18 '22 at 13:36
  • You can instead export `checkLoggedInStatus()` and use it wherever required. Also it might be better to use `onAuthStateChanged()` and return a promise as explained in [this answer](https://stackoverflow.com/q/69875003/13130697) – Dharmaraj Jun 18 '22 at 13:39
  • @CertainPerformance tried what you said : Unexpected token, expected "{" (32:7) > 32 | export isLoggedIn; – mathsnerd22 Jun 18 '22 at 13:43
  • Replacing `const` with `let` will not cause a syntax error - you must've made a typo somewhere else too – CertainPerformance Jun 18 '22 at 13:44
  • @CertainPerformance I have updated my exact code in the original post, no typos it seems – mathsnerd22 Jun 18 '22 at 13:47

1 Answers1

0

There are (at least) two problems here.


What immediately follows export may be, among other things:

  • A declaration followed by a variable name (eg export let foo = 5;) - this initializes the variable and exports it from the module in a single line
  • function or class - similar to the above
  • default, if you want to indicate what you're exporting is the default export
  • Brackets, if you're exporting identifiers that have already been declared - eg export { foo }

But doing export isLoggedIn; is invalid syntax - it falls into none of those categories (nor any of the other permitted constructs).


The other issue is that the .currentUser property may not exist yet if the auth isn't done initializing. Make sure you wait for it to be done first. Use the observer version instead.

Since that is asynchronous, you have a few options for getting that information to the rest of your script. The first one, that I'd recommend, is to have this auth module call the rest of your script (in other words, make this module your entry point, or close to it). For example:

import { initializeApp } from 'firebase/app';
import { getAuth, onAuthStateChanged } from "firebase/auth";
import { renderApp } from './renderApp';

const firebaseConfig = {
    //private keys
};

const app = initializeApp(firebaseConfig);
const auth = getAuth(app);
onAuthStateChanged(auth, (user) => {
    if (user) {
        renderApp(user);
    } else {
        // No user
        renderApp();
    }
});

where renderApp is the starting point for the rest of your code that depends on the user. You can't easily export isLoggedIn directly from the firebase module because it's retrieved asynchronously - calling renderApp with it and then passing the value around is the best way to do it.

You can also export a Promise from this firebase module script, one that resolves to whether the user is logged in or not, but that'll require all consumers of the module to have to call .then on the value before being able to use it, which could be quite messy. Better to use your firebase module script as an entry point and only call the rest of your script once the auth object has finished loading.

CertainPerformance
  • 356,069
  • 52
  • 309
  • 320
  • Thanks for the detailed response, I tried the export const isLoggedIn = auth.currentUser !== null; But when I console.log(isLoggedIn) at any one of my pages, it logs it as false, even though the user is signed in? – mathsnerd22 Jun 18 '22 at 14:16
  • See edit, it looks like your firebase auth object isn't fully initialized at the time this script runs. You'll have to redesign your app so that the auth finishes first before doing anything else in your script. – CertainPerformance Jun 18 '22 at 14:38
  • could you check the import for renderApp, there doesn't seem to be any './renderApp' library – mathsnerd22 Jun 18 '22 at 15:16
  • Like I said in the answer, you need to restructure your app a bit to account for the asynchronous nature of the auth. That's just an example module where the rest of your app starts from - make *this firebase* module the entry point for your app, and call the rest of your app from here. (Since you haven't shown any of the other code for the app, it's hard to be any more specific - but the idea is to have another module that can run the rest of your app synchronously once you have the login status) – CertainPerformance Jun 18 '22 at 15:20
  • when you say 'make this firebase module the entry point for your app', could you explain what you mean? – mathsnerd22 Jun 18 '22 at 15:32
  • Don't have any other modules perform side-effects at the top level. Have this firebase module be the first thing that runs in your app, and then have this firebase module import other parts of your app and branch from there. In other words, the control flow should start with this module and branch out to the rest of your app, instead of having different parts of your app start themselves by themselves without being called first. – CertainPerformance Jun 18 '22 at 15:35
  • I see what you mean now, just not sure if I know how to do that. I have an app.js file which is the current entry point for my app – mathsnerd22 Jun 18 '22 at 16:00
  • You can put the firebase code in that if you want, and then make sure the rest of your app is only called once the user is retrieved. Another option is to call the rest of your app immediately, but with the Firebase data integrated with it - such as with a user state that gets passed down to all children and a `useEffect` that subscribes to `onAuthStateChanged` – CertainPerformance Jun 18 '22 at 16:03