Reputation:
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 :)
Upvotes: 1
Views: 2838
Reputation: 12691
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"
}), []);
Upvotes: 4