React-Redux: Google OAuth User ID 👮♀️
Intro
In order to differentiate between our users inside of our Twitch Clone, we are going to use their Google ID Number. We can get this number with GAPI using the following process.
Getting the User ID
Once a user is logged in we can retrieve their user ID using GAPI with the following request.
gapi.auth2.getAuthInstance().currentUser.get().getId()
Of course that is just in the console, we need to request this number and track it with state inside of our application.
Saving UserId to State with Redux
We have already setup redux to track the "Signed In" status of the user, now we need to add an additional piece of state.
Currently in our component, after the component loads we start listening for changes to the authentication status of the user. If the authentication status changes, we trigger the onAuthChange
function. Depending on whether isSignedIn
is true or false we will trigger one of two actions, sign in, or sign out.
If we are signing in, we also now want to retrieve the userID. So we can simply add that request as an argument in the signIn()
function, and then manage that in the action later.
import React, { Component } from "react";
import { Link } from "react-router-dom";
import { connect } from "react-redux";
import { signIn, signOut } from "../actions";
class GoogleAuth extends Component {
componentDidMount() {
window.gapi.load("auth2", () => {
window.gapi.auth2
.init({
client_id: process.env.REACT_APP_GOOGLE_OAUTH2_CLIENT_ID,
scope: "email",
})
.then(() => {
// create auth variable
this.auth = window.gapi.auth2.getAuthInstance();
// update state so that component will re-render
this.onAuthChange(this.auth.isSignedIn.get());
// listen for changes to authentication status
this.auth.isSignedIn.listen(this.onAuthChange);
});
});
}
// triggered when authentication status changes
onAuthChange = (isSignedIn) => {
if (isSignedIn) {
this.props.signIn(this.auth.currentUser.get().getId()); // highlight-line
} else {
this.props.signOut();
}
};
// manually trigger GAPI auth change
onSignInClick = () => {
this.auth.signIn();
};
onSignOutClick = () => {
this.auth.signOut();
};
// helper function
renderAuthButton() {
if (this.props.isSignedIn === null) {
return null;
} else if (this.props.isSignedIn) {
return (
<button onClick={this.onSignOutClick} className="ui red google button">
<i className="google icon" />
Sign Out
</button>
);
} else {
return (
<button onClick={this.onSignInClick} className="ui red google button">
<i className="google icon" />
Sign In
</button>
);
}
}
render() {
return (
<Link to="/" className="item">
<div>{this.renderAuthButton()}</div>
</Link>
);
}
}
const mapStateToProps = (state) => {
return { isSignedIn: state.auth.isSignedIn };
}
export default connect(mapStateToProps, { signIn, signOut })(GoogleAuth);
then in our action we can receive that user ID as an argument, and add it as a payload in our action.
import { SIGN_IN, SIGN_OUT } from './types'
export const signIn = (userId) => { // highlight-line
return {
type: SIGN_IN,
payload: userId // highlight-line
};
};
export const signOut = () => {
return {
type: SIGN_OUT,
};
};
Which then gets sent to the reducer, where the user id is received off the payload and is added as a piece of state in the store.
import { SIGN_IN, SIGN_OUT } from '../actions/types'
const INITIAL_STATE = {
isSignedIn: null,
userId: null // highlight-line
};
export default (state = INITIAL_STATE, action) => {
switch (action.type) {
case SIGN_IN:
return {...state, isSignedIn: true, userId: action.payload }; // highlight-line
case SIGN_OUT:
return {...state, isSignedIn: false };
default:
return state;
}
};
Lastly, we want to make sure that when the user signs out we set the user ID back to null. So we can simply add that to the SIGN_OUT
reducer.
import { SIGN_IN, SIGN_OUT } from '../actions/types'
const INITIAL_STATE = {
isSignedIn: null,
userId: null
};
export default (state = INITIAL_STATE, action) => {
switch (action.type) {
case SIGN_IN:
return {...state, isSignedIn: true, userId: action.payload };
case SIGN_OUT:
return {...state, isSignedIn: false, userId: null }; // highlight-line
default:
return state;
}
};
GitHub Repo
Ncoughlin: React-Streams-Client
Comments
Recent Work
Basalt
basalt.softwareFree desktop AI Chat client, designed for developers and businesses. Unlocks advanced model settings only available in the API. Includes quality of life features like custom syntax highlighting.
BidBear
bidbear.ioBidbear is a report automation tool. It downloads Amazon Seller and Advertising reports, daily, to a private database. It then merges and formats the data into beautiful, on demand, exportable performance reports.