There are many opinionated solutions for building a React Login with Google Firebase. I generally prefer an approach where the user isn’t shown the main UI until he is logged in. And if the user logs out, we immediately kick him back to the login screen. Luckily, this isn’t hard to do at all.
Dependencies
The only dependency you will need is the Firebase API. You can install this form the Node Package Manager. I’m also going to be using Bootstrap for this project, but that’s just a stylistic choice that isn’t relevant to this tutorial.
npm install --save firebase
Create a Firebase Config File
First, make sure that you created a new project using the Firebase Dashboard. When you set up your project, it will provide you with a Javascript config that you can paste in your HTML.
In your React project, create a folder underneath source called config. Inside of that folder, create a file called Fire.js. We are going to post the contents in that file and export it.
Fire.js
import firebase from 'firebase';
const config = { /* COPY THE ACTUAL CONFIG FROM FIREBASE CONSOLE */
apiKey: 'AIzaSyD_PxFjzcPKX50pq3ITq6Q69fuHvCowMtE',
authDomain: 'visual-studio-sync.firebaseapp.com',
databaseurl: notes'https://visual-studio-sync.firebaseio.com',
projectId: 'visual-studio-sync',
storageBucket: 'visual-studio-sync.appspot.com',
messagingSenderId: '691628632398'
};
const fire = firebase.initializeApp(config);
export default fire;
We will import this object whenever we need to use the Firebase API.
Setting Up Login
Now it’s time we begin setting up the Login. We are going to use Firebase Auth listener to detect any potential logins. If the login was successful, auth listener will return us a user which we can save to state and write to local storage (optional). If the user logs out, we clear the state and route them back to Login.
App.js
import React, { Component } from 'react';
import './App.css';
import fire from './config/Fire';
import Home from './Home';
import Login from './Login';
class App extends Component {
constructor() {
super();
this.state = ({
user: null,
});
this.authListener = this.authListener.bind(this);
}
componentDidMount() {
this.authListener();
}
authListener() {
fire.auth().onAuthStateChanged((user) => {
console.log(user);
if (user) {
this.setState({ user });
localStorage.setItem('user', user.uid);
} else {
this.setState({ user: null });
localStorage.removeItem('user');
}
});
}
render() {
return (
<div>{this.state.user ? : ( <Home/>) : (<Login />)}</div>
}
}
export default App;
Pay attention to the _authListener() _function. This function is being called on componentDidMount. It’s listening to any sign our signout changes. If the user signs in, we are saving it to the state and writing the UID to local storage. Then we are using conditional rendering to the check if the component’s state.user property is defined. If it is, we are showing home. If it’s not, we are showing Login.
Login.js
Here is out Login component:
import React, { Component } from 'react';
import { Link } from 'react-router-dom';
import fire from './config/Fire';
class Login extends Component {
constructor(props) {
super(props);
this.login = this.login.bind(this);
this.handleChange = this.handleChange.bind(this);
this.signup = this.signup.bind(this);
this.state = {
email: '',
password: ''
};
}
handleChange(e) {
this.setState({ [e.target.name]: e.target.value });
}
login(e) {
e.preventDefault();
fire.auth().signInWithEmailAndPassword(this.state.email, this.state.password).then((u)=>{
}).catch((error) => {
console.log(error);
});
}
signup(e){
e.preventDefault();
fire.auth().createUserWithEmailAndPassword(this.state.email, this.state.password).then((u)=>{
}).then((u)=>{console.log(u)})
.catch((error) => {
console.log(error);
})
}
render() {
return (
<div className="col-md-6">
<form>
<div class="form-group">
<label for="exampleInputEmail1">Email address</label>
<input value={this.state.email} onChange={this.handleChange} type="email" name="email" class="form-control" id="exampleInputEmail1" aria-describedby="emailHelp" placeholder="Enter email" />
<small id="emailHelp" class="form-text text-muted">We'll never share your email with anyone else.</small>
</div>
<div class="form-group">
<label for="exampleInputPassword1">Password</label>
<input value={this.state.password} onChange={this.handleChange} type="password" name="password" class="form-control" id="exampleInputPassword1" placeholder="Password" />
</div>
<button type="submit" onClick={this.login} class="btn btn-primary">Login</button>
<button onClick={this.signup} style={{marginLeft: '25px'}} className="btn btn-success">Signup</button>
</form>
</div>
);
}
}
export default Login;
The only thing to pay attention to is the login() and signup() function. In the login function, we call Firebases’ signInWIthEmailAndPassword() function and pass in the email and password. Notice that this function is a promise. We don’t really need anything in the then() because our authListener defined in App.js will immediately route the user to Home if the login was successful.
The signup() function create the user with the specified email and password. After creation, the user will be automatically logged in. So the Auth listener in App.js will redirect them to Home.
Home.js
This one is simple. We simply have a button that will log the user out. Again, the auth listener will detect the change and route the user back to Login.
import React, { Component } from 'react';
import fire from './config/Fire';
class Home extends Component {
constructor(props) {
super(props);
this.logout = this.logout.bind(this);
}
logout() {
fire.auth().signOut();
}
render() {
return (
);
}
}
export default Home;
Your firebase console will show users who signup and when they last logged in:
That’s it. Like I mentioned, Firebase and React work will together and setting up a React Login with Firebase can save you tons of time over dealing with authentication issues.
You can view the full code on GitHub