0

I am having an issue sorting through posts by date in safari. All works as expected in Chrome.

First I fetch all the posts from my API. I then fetch some posts from the facebook api. These get combined together in an array.

If I post a new post, it publishes it to facebook and sends back the post to display on my website. In chrome it automatically sorts this by date and is added in the right spot. In safari, all the new facebook posts get added to the end of the array - unsorted by date. They appear at the end of the list.

Even if I refresh the page, the 'new' posts remain at the end of the list.

OK heres an even weirder aspect. If I switch back to chrome it sorts them correctly. When I switch back to safari - They then get sorted correctly. It is almost like whatever happens in chrome resets the ability to sort the list in safari.

Here is my sort function

{clicked === 'feed' ? (posts.sort((a, b) => 
                new Date(b.date) - new Date(a.date)
            ).map((post) => {
                    return <div key={post.postId} >{convertPost(post)}</div>
                })) : null }

Here is how I am fetching the posts -

    const getPosts = async () => {
        console.log('getting posts on posts')
        const token = await getTokenSilently();

        try {
            //Get ODB 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)
            if(!responseData.fbData){
                setPosts(responseData.posts)
            }

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

ok... more interesting things discovered - '.sort' not working on Safari

I added 1 : -1 to my sort function. It then initially sorts the safari array correctly, then starts reversing it over and over. Chrome works.

{clicked === 'feed' ? (posts.sort((a, b) => 
                new Date(b.date) > new Date(a.date) ? 1 : -1
            ).map((post) => {
                    return <div key={post.postId} >{convertPost(post)}</div>
                })) : null }
Nick McLean
  • 601
  • 1
  • 9
  • 23

1 Answers1

0

Based on this answer, Safari has (or at least had) problems with dates that represent the time zone with 4 digits, without a semicolon. Unfortunately, Facebook returns date in this format "2020-02-13T16:14:34+0000", so this must be your problem.

To fix it, you could just add the colon when processing posts from Facebook (and other services that use this format)

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)
    }
})
Adam Jeliński
  • 1,708
  • 1
  • 10
  • 21
  • It looks like this is it! Wow! Thanks again Adam! Do you have a website or paypal or venmo or something. You deserve more than a thank you for all the help you have given me. – Nick McLean May 15 '20 at 20:25
  • I'm very happy the solution worked! Thank you very much for your generosity, but I'm doing this purely for the satisfaction of helping someone and allowing them to reach their goals. I don't even have a website, but you can check out my [github profile](https://github.com/charodziej), maybe you will find something interesting there :D – Adam Jeliński May 16 '20 at 15:54
  • Hey Adam! Trying to expand this function a little more. I want to be able to get the length of the posts array and set the state to the length so I can conditionally show a button if there are more posts to see. Is this possible? - https://stackoverflow.com/questions/62154265/how-to-extract-length-of-this-array-while-mapping – Nick McLean Jun 02 '20 at 14:55