The app I am working on allows users to connect social media integrations facebook, instagram, and youtube, into my app. Once connected it pulls all of their posts from those services and puts it into one place - my app.
For example... the user can solely connect facebook. Or the user can connect all three.
The problem is if they connect all three, my newest integration (youtube) doesn't add the posts to the page. I beleive its because of how I am storing the posts - in React State.
My code below does the following.. It fetches the native posts to my platform. Then if the user has youtube connected, it fetches the youtube posts and adds them to the native posts. After this I have another if/else statement that says if the user has connected facebook or instagram it fetches those posts, and adds them to the all the posts.
What happens is, if the user has connected all three, then the fetched youtube posts, which have been added, get overwritten with the new fb or instagram posts. - I am looking for recommendations on how to code this so that it still conditionally fetches the youtube posts, but doesn't overwrite them when its all over. I'll explain how it works in the comments in the code as well.
I guess I need to figure out how to get my youtube posts in a higher scope, so that they dont get overwritten.
Thanks!
const getPosts = async () => {
const token = await getTokenSilently();
try {
//Get ODB/Native Posts
let response = await fetch(`/api/autoquotegenerators/${_id}`, {
headers: {
Authorization: `bearer ${token}`,
"Content-Type": "application/json; charset=UTF-8",
}
});
const responseData = await response.json()
setBand(responseData)
setYoutube(responseData.youtube)
setFavorites(responseData.favorites)
setFbData(responseData.fbData)
setGoogleData(responseData.googleData)
if(!responseData.fbData){
setPosts(responseData.posts)
}
//Get New Youtube Posts if the user connects Youtube.
if(responseData.googleData){
let apiKey = process.env.REACT_APP_GOOGLE_API
//Get Youtube Uploads Playlist Id
let response = await fetch(`https://www.googleapis.com/youtube/v3/channels?part=contentDetails&id=${responseData.googleData.channelId}&key=${apiKey}`)
let playlistIdResponse = await response.json()
let uploadsPlayListId = playlistIdResponse.items[0].contentDetails.relatedPlaylists.uploads
//Get Videos from Uploads Playlist
response = await fetch(`https://www.googleapis.com/youtube/v3/playlistItems?playlistId=${uploadsPlayListId}&key=${apiKey}&part=snippet&maxResults=50`)
let videosResponse = await response.json()
//Create Youtube Posts
let youtubeFormattedPosts = []
videosResponse.items.forEach(video => {
let youtubeVideoObject = {
type: "video",
data: video.snippet.resourceId.videoId,
date: video.snippet.publishedAt,
postId: video.id,
rockOn: []
}
youtubeFormattedPosts.push(youtubeVideoObject)
})
//Set All Posts - This works, if no other apis get called.
setPosts([
...responseData.posts,
...youtubeFormattedPosts
.filter(({postId}) =>
!responseData.posts
.find(post => post.postId == postId)),
])
}
let fbDataTemp = responseData.fbData
if(responseData.fbData && !responseData.fbData.instaId){
//Get Only FB and ODB Posts
//Get Fb Posts
let fbFormattedPosts = []
response = await fetch(`https://graph.facebook.com/${fbDataTemp.pageId}/feed?access_token=${fbDataTemp.pageAccessTokenLong}`)
let fbPosts = await response.json()
fbPosts.data.forEach(post => {
if(post.message){
let fbPostObject = {
type: 'text',
data: post.message,
link: `http://www.facebook.com/${post.id}`,
date: post.created_time.slice(0, -2) + ':' + post.created_time.slice(-2),
postId: post.id,
rockOn: []
}
fbFormattedPosts.push(fbPostObject)
}
})
//Set All Posts
setPosts([
...responseData.posts,
...fbFormattedPosts
.filter(({postId}) =>
!responseData.posts
.find(post => post.postId == postId)),
])
}else if(responseData.fbData && responseData.fbData.instaId){
//First Get Fb Posts
let fbFormattedPosts = []
response = await fetch(`https://graph.facebook.com/${fbDataTemp.pageId}/feed?access_token=${fbDataTemp.pageAccessTokenLong}`)
let fbPosts = await response.json()
fbPosts.data.forEach(post => {
if(post.message){
let fbPostObject = {
type: 'text',
data: post.message,
link: `http://www.facebook.com/${post.id}`,
date: post.created_time.slice(0, -2) + ':' + post.created_time.slice(-2),
postId: post.id,
rockOn: []
}
fbFormattedPosts.push(fbPostObject)
}
})
//Get IG Media Ids
let instaFormattedPosts = []
response = await fetch(`https://graph.facebook.com/v7.0/${fbDataTemp.instaId}/media?access_token=${fbDataTemp.pageAccessTokenLong}`)
let instaPosts = await response.json()
//Get IG Posts
for (let i=0 ; i< instaPosts.data.length ; i++) {
const instaId = instaPosts.data[i];
const instaResponse = await fetch(`https://graph.facebook.com/${instaId.id}?fields=id,media_url,timestamp,username&access_token=${fbDataTemp.pageAccessTokenLong}`)
let instaPostRendered = await instaResponse.json()
let instaPostObject = {
type: 'instagram',
data: instaPostRendered.media_url,
link: `http://www.instagram.com/${instaPostRendered.username}`,
date: instaPostRendered.timestamp,
postId: instaPostRendered.id,
rockOn: [],
}
instaFormattedPosts.push(instaPostObject)
}
//Set All Posts
setPosts([
...responseData.posts,
...fbFormattedPosts
.filter(({postId}) =>
!responseData.posts
.find(post => post.postId == postId)),
...instaFormattedPosts
.filter(({postId}) =>
!responseData.posts
.find(post => post.postId == postId))
])
}
} catch (error) {
console.log(error)
}
}
I guess the way I am thinking of fixing this is to using var instead of let to define the arrays that hold the posts after fetching. Then just setting AllPosts at once?
Since you have multiple setState calls being executed in the function, hence certain fields get overriden
The solution is to save all the posts in a variable and trigger setPosts
once in the end of the function
const getPosts = async () => {
const token = await getTokenSilently();
try {
//Get ODB/Native Posts
let response = await fetch(`/api/autoquotegenerators/${_id}`, {
headers: {
Authorization: `bearer ${token}`,
"Content-Type": "application/json; charset=UTF-8",
}
});
const responseData = await response.json()
setBand(responseData)
setYoutube(responseData.youtube)
setFavorites(responseData.favorites)
setFbData(responseData.fbData)
setGoogleData(responseData.googleData);
let newPosts = [];
if(!responseData.fbData){
newPosts = responseData.posts;
}
//Get New Youtube Posts if the user connects Youtube.
if(responseData.googleData){
let apiKey = process.env.REACT_APP_GOOGLE_API
//Get Youtube Uploads Playlist Id
let response = await fetch(`https://www.googleapis.com/youtube/v3/channels?part=contentDetails&id=${responseData.googleData.channelId}&key=${apiKey}`)
let playlistIdResponse = await response.json()
let uploadsPlayListId = playlistIdResponse.items[0].contentDetails.relatedPlaylists.uploads
//Get Videos from Uploads Playlist
response = await fetch(`https://www.googleapis.com/youtube/v3/playlistItems?playlistId=${uploadsPlayListId}&key=${apiKey}&part=snippet&maxResults=50`)
let videosResponse = await response.json()
//Create Youtube Posts
let youtubeFormattedPosts = []
videosResponse.items.forEach(video => {
let youtubeVideoObject = {
type: "video",
data: video.snippet.resourceId.videoId,
date: video.snippet.publishedAt,
postId: video.id,
rockOn: []
}
youtubeFormattedPosts.push(youtubeVideoObject)
})
//Set All Posts - This works, if no other apis get called.
newPosts = [
...responseData.posts,
...youtubeFormattedPosts
.filter(({postId}) =>
!responseData.posts
.find(post => post.postId == postId)),
];
}
let fbDataTemp = responseData.fbData
if(responseData.fbData && !responseData.fbData.instaId){
//Get Only FB and ODB Posts
//Get Fb Posts
let fbFormattedPosts = []
response = await fetch(`https://graph.facebook.com/${fbDataTemp.pageId}/feed?access_token=${fbDataTemp.pageAccessTokenLong}`)
let fbPosts = await response.json()
fbPosts.data.forEach(post => {
if(post.message){
let fbPostObject = {
type: 'text',
data: post.message,
link: `http://www.facebook.com/${post.id}`,
date: post.created_time.slice(0, -2) + ':' + post.created_time.slice(-2),
postId: post.id,
rockOn: []
}
fbFormattedPosts.push(fbPostObject)
}
})
//Set All Posts
newPosts = [
...newPosts,
...fbFormattedPosts
.filter(({postId}) =>
!newPosts
.find(post => post.postId == postId)),
]
}else if(responseData.fbData && responseData.fbData.instaId){
//First Get Fb Posts
let fbFormattedPosts = []
response = await fetch(`https://graph.facebook.com/${fbDataTemp.pageId}/feed?access_token=${fbDataTemp.pageAccessTokenLong}`)
let fbPosts = await response.json()
fbPosts.data.forEach(post => {
if(post.message){
let fbPostObject = {
type: 'text',
data: post.message,
link: `http://www.facebook.com/${post.id}`,
date: post.created_time.slice(0, -2) + ':' + post.created_time.slice(-2),
postId: post.id,
rockOn: []
}
fbFormattedPosts.push(fbPostObject)
}
})
//Get IG Media Ids
let instaFormattedPosts = []
response = await fetch(`https://graph.facebook.com/v7.0/${fbDataTemp.instaId}/media?access_token=${fbDataTemp.pageAccessTokenLong}`)
let instaPosts = await response.json()
//Get IG Posts
for (let i=0 ; i< instaPosts.data.length ; i++) {
const instaId = instaPosts.data[i];
const instaResponse = await fetch(`https://graph.facebook.com/${instaId.id}?fields=id,media_url,timestamp,username&access_token=${fbDataTemp.pageAccessTokenLong}`)
let instaPostRendered = await instaResponse.json()
let instaPostObject = {
type: 'instagram',
data: instaPostRendered.media_url,
link: `http://www.instagram.com/${instaPostRendered.username}`,
date: instaPostRendered.timestamp,
postId: instaPostRendered.id,
rockOn: [],
}
instaFormattedPosts.push(instaPostObject)
}
//Set All Posts
newPosts = [
...newPosts,
...instaFormattedPosts
.filter(({postId}) =>
!newPosts
.find(post => post.postId == postId))
];
}
setPosts(newPosts);
} catch (error) {
console.log(error)
}
}