【问题标题】:Fetching with if statements - Conditional Fetching Problems使用 if 语句获取 - 条件获取问题
【发布时间】:2020-09-11 05:21:54
【问题描述】:

我正在开发的应用程序允许用户将社交媒体集成 facebook、instagram 和 youtube 连接到我的应用程序中。连接后,它会从这些服务中提取他们的所有帖子并将其放在一个地方 - 我的应用程序。

例如...用户可以单独连接 facebook。或者用户可以连接所有三个。

问题是,如果它们连接所有三个,我最新的集成 (y​​outube) 不会将帖子添加到页面。我相信它是因为我存储帖子的方式 - 在 React 状态下。

我下面的代码执行以下操作。它将本机帖子提取到我的平台。然后,如果用户连接了 youtube,它会获取 youtube 帖子并将它们添加到本地帖子中。在此之后,我有另一个 if/else 语句,说明如果用户连接了 facebook 或 instagram,它会获取这些帖子,并将它们添加到所有帖子中。

发生的情况是,如果用户已连接所有三个,则已添加的提取的 youtube 帖子将被新的 fb 或 instagram 帖子覆盖。 - 我正在寻找有关如何编码的建议,以便它仍然有条件地获取 youtube 帖子,但不会在全部结束时覆盖它们。我还将在代码的 cmets 中解释它是如何工作的。

我想我需要弄清楚如何在更高的范围内获取我的 youtube 帖子,以免它们被覆盖。

谢谢!

 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)
    }
}

我想我想解决这个问题的方法是使用 var 而不是 let 来定义获取后保存帖子的数组。然后一次性设置 AllPosts?

【问题讨论】:

    标签: reactjs if-statement use-state fetching-strategy


    【解决方案1】:

    由于您在函数中执行了多个 setState 调用,因此某些字段会被覆盖

    解决方法是将所有帖子保存在一个变量中,并在函数结束时触发一次setPosts

    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)
        }
    }
    

    【讨论】:

    • 啊!!好的,我会试试这个 - 似乎比我目前的解决方案好得多。我打算从所有 api 调用中删除 setPosts(...fetchedPosts) 。然后将 let 变量更改为 var 以获取全局范围。然后将它们全部设置在最后一次。
    猜你喜欢
    • 2015-09-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-22
    相关资源
    最近更新 更多