Graph API requests cannot be made with a Limited Login Authentication Token on iOS. You must use an Access Token from traditional login.
Prerequisites
Before making Graph API requests:- User must be logged in with traditional Facebook Login
- You must have a valid Access Token
- User must have granted appropriate permissions
import { AccessToken } from 'react-native-fbsdk-next';
// Check if we have a valid access token
const token = await AccessToken.getCurrentAccessToken();
if (!token) {
console.log('User not logged in');
return;
}
console.log('Ready to make Graph API requests');
Making Graph Requests
Basic Request
UseGraphRequest and GraphRequestManager to make API calls:
import { GraphRequest, GraphRequestManager } from 'react-native-fbsdk-next';
function fetchUserData() {
// Create a callback to handle the response
const callback = (error, result) => {
if (error) {
console.log('Error fetching data:', error);
} else {
console.log('Success:', result);
}
};
// Create the request
const infoRequest = new GraphRequest(
'/me', // Graph API endpoint
null, // Config (optional)
callback
);
// Execute the request
new GraphRequestManager().addRequest(infoRequest).start();
}
Request with Parameters
Add parameters to customize the request:import { GraphRequest, GraphRequestManager } from 'react-native-fbsdk-next';
function fetchUserProfile() {
const callback = (error, result) => {
if (error) {
console.error('Error:', error);
} else {
console.log('User data:', result);
console.log('Name:', result.name);
console.log('Email:', result.email);
}
};
const request = new GraphRequest(
'/me',
{
parameters: {
fields: {
string: 'id,name,email,picture.type(large)',
},
},
},
callback
);
new GraphRequestManager().addRequest(request).start();
}
Using Async/Await
Wrap Graph requests in a Promise for cleaner code:import { GraphRequest, GraphRequestManager } from 'react-native-fbsdk-next';
function makeGraphRequest(path, config = {}) {
return new Promise((resolve, reject) => {
const callback = (error, result) => {
if (error) {
reject(error);
} else {
resolve(result);
}
};
const request = new GraphRequest(path, config, callback);
new GraphRequestManager().addRequest(request).start();
});
}
// Usage
async function getUserData() {
try {
const result = await makeGraphRequest('/me', {
parameters: {
fields: { string: 'id,name,email,picture' },
},
});
console.log('User:', result.name);
console.log('Email:', result.email);
return result;
} catch (error) {
console.error('Failed to fetch user data:', error);
}
}
Common Graph API Endpoints
Get User Profile
const result = await makeGraphRequest('/me', {
parameters: {
fields: { string: 'id,name,email,first_name,last_name,picture.type(large)' },
},
});
console.log('Name:', result.name);
console.log('Email:', result.email);
console.log('Picture URL:', result.picture.data.url);
Get User’s Friends
// Requires 'user_friends' permission
const result = await makeGraphRequest('/me/friends', {
parameters: {
fields: { string: 'id,name,picture' },
},
});
console.log('Friends:', result.data);
result.data.forEach(friend => {
console.log(`- ${friend.name}`);
});
Get User’s Photos
// Requires 'user_photos' permission
const result = await makeGraphRequest('/me/photos', {
parameters: {
fields: { string: 'id,name,picture,created_time' },
},
});
console.log('Photos:', result.data);
Get User’s Posts
// Requires 'user_posts' permission
const result = await makeGraphRequest('/me/posts', {
parameters: {
fields: { string: 'id,message,created_time,full_picture' },
limit: { string: '10' },
},
});
console.log('Recent posts:', result.data);
Request Configuration
HTTP Methods
Specify the HTTP method for your request:const request = new GraphRequest(
'/me/feed',
{
httpMethod: 'POST', // GET, POST, DELETE, etc.
parameters: {
message: { string: 'Posted from my React Native app!' },
},
},
callback
);
API Version
Specify a Graph API version:const request = new GraphRequest(
'/me',
{
version: 'v18.0', // Use specific API version
parameters: {
fields: { string: 'id,name' },
},
},
callback
);
Custom Access Token
Use a specific access token:const request = new GraphRequest(
'/me',
{
accessToken: 'your_access_token_here',
parameters: {
fields: { string: 'id,name' },
},
},
callback
);
Batch Requests
Make multiple Graph API requests in a single network call:import { GraphRequest, GraphRequestManager } from 'react-native-fbsdk-next';
function fetchMultipleData() {
const profileCallback = (error, result) => {
if (!error) {
console.log('Profile:', result);
}
};
const friendsCallback = (error, result) => {
if (!error) {
console.log('Friends:', result);
}
};
const photosCallback = (error, result) => {
if (!error) {
console.log('Photos:', result);
}
};
// Create multiple requests
const profileRequest = new GraphRequest(
'/me',
{ parameters: { fields: { string: 'id,name,email' } } },
profileCallback
);
const friendsRequest = new GraphRequest(
'/me/friends',
null,
friendsCallback
);
const photosRequest = new GraphRequest(
'/me/photos',
{ parameters: { limit: { string: '5' } } },
photosCallback
);
// Execute all requests in batch
new GraphRequestManager()
.addRequest(profileRequest)
.addRequest(friendsRequest)
.addRequest(photosRequest)
.start();
}
Pagination
Handle paginated results:async function fetchAllFriends() {
let allFriends = [];
let nextUrl = '/me/friends';
while (nextUrl) {
const result = await makeGraphRequest(nextUrl, {
parameters: {
fields: { string: 'id,name' },
limit: { string: '100' },
},
});
allFriends = allFriends.concat(result.data);
// Check for next page
nextUrl = result.paging?.next ? result.paging.next : null;
console.log(`Fetched ${allFriends.length} friends so far...`);
}
console.log(`Total friends: ${allFriends.length}`);
return allFriends;
}
Error Handling
Common Errors
async function handleGraphRequest() {
try {
const result = await makeGraphRequest('/me/photos');
return result;
} catch (error) {
// Parse Facebook error
if (error.message) {
console.error('Error message:', error.message);
}
if (error.code) {
switch (error.code) {
case 190:
console.error('Invalid access token');
// Prompt user to re-login
break;
case 200:
console.error('Permission denied');
// Request additional permissions
break;
case 100:
console.error('Invalid parameter');
break;
default:
console.error('Unknown error:', error.code);
}
}
}
}
Checking Permissions
Verify permissions before making requests:import { AccessToken, LoginManager } from 'react-native-fbsdk-next';
async function ensurePermission(permission) {
const token = await AccessToken.getCurrentAccessToken();
if (!token) {
throw new Error('User not logged in');
}
if (!token.permissions.includes(permission)) {
console.log(`Requesting ${permission} permission...`);
const result = await LoginManager.logInWithPermissions([permission]);
if (result.isCancelled || !result.grantedPermissions.includes(permission)) {
throw new Error(`Permission ${permission} not granted`);
}
}
return true;
}
// Usage
async function getUserPhotos() {
await ensurePermission('user_photos');
const result = await makeGraphRequest('/me/photos');
return result.data;
}
Complete Example
Here’s a complete example of fetching and displaying user data:import React, { useState, useEffect } from 'react';
import { View, Text, Image, FlatList, StyleSheet, ActivityIndicator } from 'react-native';
import { GraphRequest, GraphRequestManager, AccessToken } from 'react-native-fbsdk-next';
function makeGraphRequest(path, config = {}) {
return new Promise((resolve, reject) => {
const callback = (error, result) => {
if (error) reject(error);
else resolve(result);
};
const request = new GraphRequest(path, config, callback);
new GraphRequestManager().addRequest(request).start();
});
}
function UserProfileScreen() {
const [userData, setUserData] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
fetchUserData();
}, []);
const fetchUserData = async () => {
try {
setLoading(true);
setError(null);
// Check if user is logged in
const token = await AccessToken.getCurrentAccessToken();
if (!token) {
setError('Not logged in');
return;
}
// Fetch user profile
const result = await makeGraphRequest('/me', {
parameters: {
fields: {
string: 'id,name,email,picture.type(large),birthday,friends.limit(5){name,picture}',
},
},
});
setUserData(result);
} catch (err) {
console.error('Failed to fetch user data:', err);
setError(err.message || 'Failed to fetch data');
} finally {
setLoading(false);
}
};
if (loading) {
return (
<View style={styles.container}>
<ActivityIndicator size="large" />
</View>
);
}
if (error) {
return (
<View style={styles.container}>
<Text style={styles.error}>Error: {error}</Text>
</View>
);
}
if (!userData) {
return null;
}
return (
<View style={styles.container}>
<Image
source={{ uri: userData.picture?.data?.url }}
style={styles.profilePicture}
/>
<Text style={styles.name}>{userData.name}</Text>
{userData.email && <Text style={styles.email}>{userData.email}</Text>}
{userData.birthday && <Text>Birthday: {userData.birthday}</Text>}
{userData.friends?.data?.length > 0 && (
<View style={styles.friendsSection}>
<Text style={styles.sectionTitle}>Friends</Text>
<FlatList
data={userData.friends.data}
keyExtractor={(item) => item.id}
renderItem={({ item }) => (
<View style={styles.friendItem}>
<Image
source={{ uri: item.picture?.data?.url }}
style={styles.friendPicture}
/>
<Text>{item.name}</Text>
</View>
)}
/>
</View>
)}
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
padding: 20,
alignItems: 'center',
},
profilePicture: {
width: 150,
height: 150,
borderRadius: 75,
marginBottom: 20,
},
name: {
fontSize: 24,
fontWeight: 'bold',
marginBottom: 10,
},
email: {
fontSize: 16,
color: '#666',
marginBottom: 10,
},
friendsSection: {
marginTop: 30,
width: '100%',
},
sectionTitle: {
fontSize: 20,
fontWeight: 'bold',
marginBottom: 10,
},
friendItem: {
flexDirection: 'row',
alignItems: 'center',
marginBottom: 10,
},
friendPicture: {
width: 40,
height: 40,
borderRadius: 20,
marginRight: 10,
},
error: {
color: 'red',
fontSize: 16,
},
});
export default UserProfileScreen;
Best Practices
1. Always Check Token Validity
import { AccessToken } from 'react-native-fbsdk-next';
async function makeAuthenticatedRequest(path, config) {
const token = await AccessToken.getCurrentAccessToken();
if (!token) {
throw new Error('No access token available');
}
// Check if token is expired
if (token.expirationTime < Date.now()) {
console.log('Token expired, refreshing...');
await AccessToken.refreshCurrentAccessTokenAsync();
}
return makeGraphRequest(path, config);
}
2. Request Only Needed Fields
Be specific about which fields you need:// Bad - requests all available fields
const result = await makeGraphRequest('/me');
// Good - requests only needed fields
const result = await makeGraphRequest('/me', {
parameters: {
fields: { string: 'id,name,email' },
},
});
3. Cache Responses
Cache Graph API responses to reduce network calls:const cache = {};
async function cachedGraphRequest(path, config, ttl = 300000) {
const cacheKey = `${path}-${JSON.stringify(config)}`;
// Check cache
if (cache[cacheKey] && cache[cacheKey].expiry > Date.now()) {
console.log('Returning cached result');
return cache[cacheKey].data;
}
// Fetch fresh data
const result = await makeGraphRequest(path, config);
// Store in cache
cache[cacheKey] = {
data: result,
expiry: Date.now() + ttl,
};
return result;
}
4. Handle Rate Limiting
Facebook limits API calls. Handle rate limit errors:async function makeRequestWithRetry(path, config, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
try {
return await makeGraphRequest(path, config);
} catch (error) {
if (error.code === 4 || error.code === 17) {
// Rate limit error
const waitTime = Math.pow(2, i) * 1000; // Exponential backoff
console.log(`Rate limited. Waiting ${waitTime}ms...`);
await new Promise(resolve => setTimeout(resolve, waitTime));
} else {
throw error;
}
}
}
throw new Error('Max retries exceeded');
}
See Also
Authentication
Learn about access tokens and authentication
Graph Request API
Complete API reference for GraphRequest
Facebook Graph API Docs
Official Facebook Graph API documentation
Permissions Reference
Complete list of Facebook permissions