1

I am using Firebase auth in a React app. I am getting the error below:

Uncaught FirebaseError: Firebase: Firebase App named '[DEFAULT]' already exists (app/duplicate-app).

I am trying to configure and initialise a Firebase app to make use of the Firebase auth SDK. Using React class base components worked without any errors, but moving over to React Hooks is proving a challenge.

A simple example of where the problem is occurring:

import React, {useState, useEffect} from 'react';
import './App.css';

import * as firebase from "firebase/app";
import 'firebase/auth';

const App = () => {

  const [emailVal, setEmailVal] = useState('')
  const [passwordVal, setPasswordVal] = useState('')

  const handleChangeEmail = (event) => {
    setEmailVal(event.target.value);
  }

  const handleChangePassword = (event) =>{
    setPasswordVal(event.target.value);
  }

  const handleSubmit = (event) =>{
    event.preventDefault();
    const auth = firebase.auth()
    auth.signInWithEmailAndPassword(emailVal, passwordVal)
      .then(response=>{
        console.log(response)
      });
  }

  const firebaseConfig = {
    apiKey: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
    authDomain: "xxxxxxxxxxxxxxxxxxxxxxxxxx",
    databaseURL: "xxxxxxxxxxxxxxxxxxxxxxxxxxxx",
    projectId: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
    appId: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
  };

  console.log(firebaseConfig)

  useEffect(()=>{
    console.log("useEffect called")
    firebase.initializeApp(firebaseConfig);
  }, [firebaseConfig])


  return (
    <div className="App">
      <h1>Testing client side authentication</h1>

        <form onSubmit = {handleSubmit}>
          <label>
            Email:
            <input type="text" value={emailVal} onChange={handleChangeEmail} />
          </label>
          <label>
            Password:
            <input type="text"  value={passwordVal} onChange={handleChangePassword}/>
          </label>
          <input type="submit" value="Submit" />
        </form>

    </div>
  );
}

export default App;

When I place a console.log in useEffect it appears that the useEffect hook runs after the first render, which is good. Then when I type into the text input boxes and the component is re-rendered, the useEffect hook runs again, even though the firebaseConfig variable is unchanged. I suspect that each re-render is actually creating a new version of the firebaseConfig variable that in turn triggers the useEffect hook. To overcome this I removed the dependency from the useEffect hook like so:

 useEffect(()=>{
    console.log("useEffect called")
    firebase.initializeApp(firebaseConfig);
  }, [])

This works well, but I am getting linting warnings:

React Hook useEffect has a missing dependency: 'firebaseConfig'. Either include it or remove the dependency array react-hooks/exhaustive-deps

So my next step was to set the firebaseConfig in a useState call. But then I also get linting warnings that the setFirebaseConfig is not being used.

I would comfortably leave the dependencies empty so that that useEffect works like ComponentDidMount but then the linting warnings concern me that I may be causing a problem in my code.

Essentially, if I could somehow compare the actual values in the firebaseConfig and add that to the useEffect dependency I think it would work as the values themselves are unchanging once the app is loaded. Does anyone know how to do this?

Thanks :)

2
  • try to instead of putting config into your own object put it in state. Commented Sep 5, 2019 at 9:25
  • Thanks Maielo, that is a workable solution too. Commented Sep 5, 2019 at 9:37

1 Answer 1

4

Every render a new firebaseConfig object is created which cause the useEffect to run again.

You can move firebaseConfig outside your component.

Or you can use useMemo hook so that the firebaseConfig is not created every render, like this :

const firebaseConfig = useMemo(() => ({
    apiKey: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
    authDomain: "xxxxxxxxxxxxxxxxxxxxxxxxxx",
    databaseURL: "xxxxxxxxxxxxxxxxxxxxxxxxxxxx",
    projectId: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
    appId: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}), []);
Sign up to request clarification or add additional context in comments.

1 Comment

Great stuff Mohamed. It works and no linting issues. Thanks! I shall add useMemo to my toolbox for future use.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.