41
Using Facebook SDK with React the right way
Recently I joined KBC Bank & Verzekering as part of a new, small internal marketing team. As a full stack developer, I'm responsible for building the (web) applicatons required for marketing campaigns. One of these campaigns required logging in with Facebook. I had never worked with Facebook integration before, but I was convinced it wouldn't be too hard.
Boy, was I wrong.
React is a library built by Facebook, so it should have its own library for Facebook integration, right? Wrong. Ironically enough, Facebook only has an SDK for JavaScript. (Yes, vanilla JavaScript, not even TypeScript)
There used to be an SDK for React Native, but apparently that's no longer being supported either.
This means we're on our own.
My first instinct was to look for 3rd party libraries. A library that immediately caught my attention was react-facebook-login. I tried it and it did what it had to do, but its functionality was very limited and the library hadn't been updated in years, while having 71 open issues and 5 open pull requests at the time of writing.
Other libraries, like react-facebook, showed similar patterns. I wasn't convinced.
As Napoléon Bonaparte once said: if you want something done, do it yourself.
We could just add the SDK for JavaScript to the index.html
, but that's not something we want to do. We might not want to include the SDK on every page. Instead, it might be a good idea to build a wrapper for the SDK using React Hooks. This gives us access to all functionality provided by Facebook, while still keeping full control.
The first step is loading the script into the page, so let's create a new React Hook that does just that:
const useFacebook = () => {
useEffect(() => {
const script = document.createElement("script");
script.async = true;
script.defer = true;
script.crossOrigin = "anonymous";
script.src = `https://connect.facebook.net/nl_BE/sdk.js`;
document.body.appendChild(script);
window.fbAsyncInit = function () {
FB.init({
appId: <ENTER YOUR FACEBOOK APP ID HERE>,
autoLogAppEvents: true,
xfbml: true,
version: "v11.0",
});
};
return () => {
delete window.fbAsyncInit;
document.body.removeChild(script);
};
}, []);
};
As you can see, we also remove the script as soon as the hook is not in use anymore.
If you're using TypeScript, you might already run into some issues: we're setting the fbAsyncInit
property on window
, which doesn't have that property to begin with. We need to add this property to the Window interface by adding the following code:
declare global {
interface Window {
fbAsyncInit?: Function;
}
}
Another issue you might run into is that TypeScript is unaware of the FB
variable that gets inserted by the script. You can fix this by adding @types/facebook-js-sdk
to your project:
npm install @types/facebook-js-sdk --save-dev
We should be able to follow along with the official docs now.
The SDK makes use of callbacks, but we're fancy, so we are going to turn them into promises.
Let's illustrate this with the FB.login
function. By default, the FB.login
function returns a response, regardless of the result. Let's turn this into a promise that returns the response if the login is successful and throws an error otherwise:
const login = () => {
return new Promise<fb.StatusResponse>((resolve, reject) => {
FB.login((response) => {
if (response.status === "connected") resolve(response);
else reject(new Error("Facebook login failed"));
});
});
};
In case you're wondering where fb.StatusResponse
comes from: it's a type used in TypeScript that comes from @types/facebook-js-sdk
.
Et voilà! You should have successfully integrated the Facebook SDK in your React application, the right way.
41