React + Facebook - How to use the Facebook SDK in a React App
Other versions available:
This is a quick post to go through the steps to load, initialize and use the Facebook JS SDK in a React application.
The below code snippets are from a Facebook login tutorial I posted recently, for the full tutorial and live demo of the code see React - Facebook Login Tutorial & Example.
Init the Facebook SDK in a React App Before Startup
The below initFacebookSdk()
function runs before the React app starts up to load and initialize the Facebook SDK, and automatically log the user into the React app if they are already logged in with Facebook.
The init Facebook SDK function is called from the index.js file which waits for the returned Promise to be resolved before starting the React app.
import { accountService } from '_services';
const facebookAppId = process.env.REACT_APP_FACEBOOK_APP_ID;
export function initFacebookSdk() {
return new Promise(resolve => {
// wait for facebook sdk to initialize before starting the react app
window.fbAsyncInit = function () {
window.FB.init({
appId: facebookAppId,
cookie: true,
xfbml: true,
version: 'v8.0'
});
// auto authenticate with the api if already logged in with facebook
window.FB.getLoginStatus(({ authResponse }) => {
if (authResponse) {
accountService.apiAuthenticate(authResponse.accessToken).then(resolve);
} else {
resolve();
}
});
};
// load facebook sdk script
(function (d, s, id) {
var js, fjs = d.getElementsByTagName(s)[0];
if (d.getElementById(id)) { return; }
js = d.createElement(s); js.id = id;
js.src = "https://connect.facebook.net/en_US/sdk.js";
fjs.parentNode.insertBefore(js, fjs);
}(document, 'script', 'facebook-jssdk'));
});
}
Example React Index.js Startup File
The index.js file from the example project bootstraps the React application by rendering the App
component () in the #app
div element defined in the main index html file.
The index.js file from the example project bootstraps the React application by rendering the App
component (wrapped in a Router
) into the app
div element defined in the main index html file.
Before starting the React app it performs a number of pre-startup tasks, including waiting for the Facebook SDK to load and initialize on line 20
.
import React from 'react';
import { Router } from 'react-router-dom';
import { render } from 'react-dom';
// global stylesheet
import './index.css';
import { initFacebookSdk, jwtInterceptor, errorInterceptor, history } from './_helpers';
import { App } from './App';
// setup fake backend
import { fakeBackend } from './_helpers';
fakeBackend();
// enable interceptors for http requests
jwtInterceptor();
errorInterceptor();
// wait for facebook sdk before startup
initFacebookSdk().then(startApp);
function startApp() {
render(
<Router history={history}>
<App />
</Router>,
document.getElementById('app')
);
}
Use the Facebook SDK in your React App!
You're now ready to use the Facebook SDK in your React app, as an example here is the account service (/src/_services/account.service.js
) from the Facebook login example project, it uses some Facebook SDK auth methods on lines 23
, 45
and 92
.
import { BehaviorSubject } from 'rxjs';
import axios from 'axios';
import { history } from '_helpers';
const baseUrl = `${process.env.REACT_APP_API_URL}/accounts`;
const accountSubject = new BehaviorSubject(null);
export const accountService = {
login,
apiAuthenticate,
logout,
getAll,
getById,
update,
delete: _delete,
account: accountSubject.asObservable(),
get accountValue () { return accountSubject.value; }
};
async function login() {
// login with facebook then authenticate with the API to get a JWT auth token
const { authResponse } = await new Promise(window.FB.login);
if (!authResponse) return;
await apiAuthenticate(authResponse.accessToken);
// get return url from location state or default to home page
const { from } = history.location.state || { from: { pathname: "/" } };
history.push(from);
}
async function apiAuthenticate(accessToken) {
// authenticate with the api using a facebook access token,
// on success the api returns an account object with a JWT auth token
const response = await axios.post(`${baseUrl}/authenticate`, { accessToken });
const account = response.data;
accountSubject.next(account);
startAuthenticateTimer();
return account;
}
function logout() {
// revoke app permissions to logout completely because FB.logout() doesn't remove FB cookie
window.FB.api('/me/permissions', 'delete', null, () => window.FB.logout());
stopAuthenticateTimer();
accountSubject.next(null);
history.push('/login');
}
function getAll() {
return axios.get(baseUrl)
.then(response => response.data);
}
function getById(id) {
return axios.get(`${baseUrl}/${id}`)
.then(response => response.data);
}
async function update(id, params) {
const response = await axios.put(`${baseUrl}/${id}`, params);
let account = response.data;
// update the current account if it was updated
if (account.id === accountSubject.value?.id) {
// publish updated account to subscribers
account = { ...accountSubject.value, ...account };
accountSubject.next(account);
}
return account;
}
async function _delete(id) {
await axios.delete(`${baseUrl}/${id}`);
if (id === accountSubject.value?.id) {
// auto logout if the logged in account was deleted
logout();
}
}
// helper methods
let authenticateTimeout;
function startAuthenticateTimer() {
// parse json object from base64 encoded jwt token
const jwtToken = JSON.parse(atob(accountSubject.value.token.split('.')[1]));
// set a timeout to re-authenticate with the api one minute before the token expires
const expires = new Date(jwtToken.exp * 1000);
const timeout = expires.getTime() - Date.now() - (60 * 1000);
const { accessToken } = window.FB.getAuthResponse();
authenticateTimeout = setTimeout(() => apiAuthenticate(accessToken), timeout);
}
function stopAuthenticateTimer() {
// cancel timer for re-authenticating with the api
clearTimeout(authenticateTimeout);
}
Need Some Facebook Help?
Search fiverr for freelance Facebook developers.
Follow me for updates
When I'm not coding...
Me and Tina are on a motorcycle adventure around Australia.
Come along for the ride!