React Facebook works seamlessly with SSR frameworks like Next.js and Remix. Use the lazy loading feature to prevent SDK initialization on the server.
1// Next.js App Router example2import { FacebookProvider } from 'react-facebook';3
4export default function RootLayout({ children }) {5 return (6 <html>7 <body>8 <FacebookProvider 9 appId={process.env.NEXT_PUBLIC_FB_APP_ID}10 lazy={true} // Important for SSR11 >12 {children}13 </FacebookProvider>14 </body>15 </html>16 );17}18
19// pages/_app.js for Next.js Pages Router20import { FacebookProvider } from 'react-facebook';21
22function MyApp({ Component, pageProps }) {23 return (24 <FacebookProvider 25 appId={process.env.NEXT_PUBLIC_FB_APP_ID}26 lazy={typeof window === 'undefined'} // Skip on server27 >28 <Component {...pageProps} />29 </FacebookProvider>30 );31}
Implement robust error handling with retry logic and fallback UI for better user experience.
1import { useFacebook, LoginButton } from 'react-facebook';2import { useEffect, useState } from 'react';3
4function RobustLoginComponent() {5 const { error: sdkError, init } = useFacebook();6 const [loginError, setLoginError] = useState(null);7 const [retryCount, setRetryCount] = useState(0);8
9 // Handle SDK initialization errors10 useEffect(() => {11 if (sdkError) {12 console.error('Facebook SDK Error:', sdkError);13 14 // Retry logic15 if (retryCount < 3) {16 setTimeout(() => {17 init();18 setRetryCount(prev => prev + 1);19 }, 2000 * Math.pow(2, retryCount)); // Exponential backoff20 }21 }22 }, [sdkError, retryCount]);23
24 const handleLoginError = (error) => {25 setLoginError(error);26 27 // Handle specific error types28 if (error.code === 'FACEBOOK_SDK_NOT_LOADED') {29 // SDK not loaded, try initializing30 init();31 } else if (error.code === 'USER_CANCELLED') {32 // User cancelled login33 console.log('User cancelled login');34 } else {35 // Other errors36 console.error('Login error:', error);37 }38 };39
40 if (sdkError && retryCount >= 3) {41 return (42 <div className="error-fallback">43 <p>Unable to load Facebook login. Please try again later.</p>44 <button onClick={() => window.location.reload()}>45 Refresh Page46 </button>47 </div>48 );49 }50
51 return (52 <div>53 {loginError && (54 <div className="error-message">55 Login failed: {loginError.message}56 </div>57 )}58 59 <LoginButton60 scope="email,public_profile"61 onFail={handleLoginError}62 onSuccess={(response) => console.log('Success!', response)}63 >64 Login with Facebook65 </LoginButton>66 </div>67 );68}
Optimize bundle size and loading performance with lazy loading and code splitting.
1// Lazy loading Facebook SDK2import { FacebookProvider } from 'react-facebook';3import { lazy, Suspense } from 'react';4
5// Lazy load components that use Facebook SDK6const FacebookLogin = lazy(() => import('./FacebookLogin'));7const FacebookComments = lazy(() => import('./FacebookComments'));8
9function App() {10 return (11 <FacebookProvider 12 appId="YOUR_APP_ID" 13 lazy={true} // Don't load until needed14 >15 <div>16 {/* SDK loads when this component renders */}17 <Suspense fallback={<div>Loading...</div>}>18 <FacebookLogin />19 </Suspense>20 21 {/* Comments load on demand */}22 <Suspense fallback={<div>Loading comments...</div>}>23 <FacebookComments />24 </Suspense>25 </div>26 </FacebookProvider>27 );28}29
30// Code splitting with dynamic imports31function DynamicFacebookFeatures() {32 const [showComments, setShowComments] = useState(false);33
34 const loadComments = async () => {35 const { Comments } = await import('react-facebook');36 setShowComments(true);37 };38
39 return (40 <div>41 <button onClick={loadComments}>Load Comments</button>42 {showComments && <Comments href="..." />}43 </div>44 );45}
Implement proper authentication flow with server-side token verification for production applications.
1// Security best practices2import { useLogin } from 'react-facebook';3
4function SecureLogin() {5 const { login } = useLogin();6
7 const handleLogin = async () => {8 try {9 const response = await login({10 scope: 'email,public_profile',11 auth_type: 'rerequest', // Force re-authentication12 return_scopes: true // Get actual granted permissions13 });14
15 if (response.authResponse) {16 // Send token to your backend for verification17 const verified = await verifyTokenOnServer(response.authResponse.accessToken);18 19 if (verified) {20 // Store session securely (not in localStorage!)21 // Use httpOnly cookies or secure session storage22 await createSecureSession(verified.sessionToken);23 }24 }25 } catch (error) {26 console.error('Login failed:', error);27 }28 };29
30 return <button onClick={handleLogin}>Secure Login</button>;31}32
33// Backend token verification (Node.js example)34async function verifyTokenOnServer(accessToken) {35 const response = await fetch(36 `https://graph.facebook.com/me?access_token=${accessToken}&fields=id,name,email`37 );38 39 const data = await response.json();40 41 if (data.error) {42 throw new Error('Invalid token');43 }44 45 // Additional verification with app secret46 const appProof = crypto47 .createHmac('sha256', process.env.FB_APP_SECRET)48 .update(accessToken)49 .digest('hex');50 51 // Verify the token belongs to your app52 // Create secure session53 return { 54 userId: data.id, 55 sessionToken: generateSecureToken() 56 };57}
Implement consent management for Facebook Pixel and ensure GDPR compliance.
1// GDPR Compliance with consent management2import { FacebookProvider, usePixel } from 'react-facebook';3import { useState, useEffect } from 'react';4
5function GDPRCompliantApp() {6 const [hasConsent, setHasConsent] = useState(false);7
8 useEffect(() => {9 // Check for existing consent10 const consent = localStorage.getItem('fb_tracking_consent');11 setHasConsent(consent === 'granted');12 }, []);13
14 const handleConsent = (granted) => {15 setHasConsent(granted);16 localStorage.setItem('fb_tracking_consent', granted ? 'granted' : 'denied');17 };18
19 return (20 <FacebookProvider 21 appId="YOUR_APP_ID"22 pixel={{23 pixelId: "YOUR_PIXEL_ID",24 autoConfig: false, // Don't auto-track25 }}26 >27 {!hasConsent && <ConsentBanner onConsent={handleConsent} />}28 <ConditionalPixelTracking enabled={hasConsent} />29 {/* Your app */}30 </FacebookProvider>31 );32}33
34function ConditionalPixelTracking({ enabled }) {35 const { grantConsent, revokeConsent, pageView } = usePixel();36
37 useEffect(() => {38 if (enabled) {39 grantConsent();40 pageView(); // Track after consent41 } else {42 revokeConsent();43 }44 }, [enabled]);45
46 return null;47}48
49function ConsentBanner({ onConsent }) {50 return (51 <div className="consent-banner">52 <p>We use cookies and similar technologies...</p>53 <button onClick={() => onConsent(true)}>Accept</button>54 <button onClick={() => onConsent(false)}>Decline</button>55 </div>56 );57}
Comprehensive testing approach for Facebook integrations including unit and E2E tests.
1// Testing with Jest and React Testing Library2import { render, screen, waitFor } from '@testing-library/react';3import { FacebookProvider, LoginButton } from 'react-facebook';4import userEvent from '@testing-library/user-event';5
6// Mock Facebook SDK7jest.mock('react-facebook', () => ({8 FacebookProvider: ({ children }) => <div>{children}</div>,9 LoginButton: jest.fn(({ children, onSuccess, onFail }) => (10 <button onClick={() => onSuccess({ authResponse: mockAuthResponse })}>11 {children}12 </button>13 )),14}));15
16const mockAuthResponse = {17 accessToken: 'mock-token',18 userID: '123456',19 expiresIn: 3600,20 signedRequest: 'mock-signed-request',21};22
23describe('Facebook Login', () => {24 it('should handle successful login', async () => {25 const handleSuccess = jest.fn();26 27 render(28 <FacebookProvider appId="test-app-id">29 <LoginButton onSuccess={handleSuccess}>30 Login31 </LoginButton>32 </FacebookProvider>33 );34 35 const button = screen.getByText('Login');36 await userEvent.click(button);37 38 await waitFor(() => {39 expect(handleSuccess).toHaveBeenCalledWith({40 authResponse: mockAuthResponse41 });42 });43 });44});45
46// E2E testing with Cypress47describe('Facebook Integration', () => {48 beforeEach(() => {49 cy.visit('/');50 // Stub Facebook SDK51 cy.window().then((win) => {52 win.FB = {53 init: cy.stub(),54 login: cy.stub().callsFake((callback) => {55 callback({ authResponse: mockAuthResponse });56 }),57 };58 });59 });60
61 it('should login with Facebook', () => {62 cy.get('[data-testid="fb-login-button"]').click();63 cy.get('[data-testid="user-profile"]').should('be.visible');64 });65});
Ensure FacebookProvider is only used once at the root of your app. Multiple providers will cause conflicts.
Add all your domains (including localhost for development) to your Facebook App settings.
Use environment variables for App IDs and ensure you're using the correct ID for each environment.
Always check if the SDK is loaded before making API calls. Use the isLoading state from hooks.