1

I have an array of posts that I am trying to sort by date - I cant figure out how to get access to the date though, since the array is a list of react components, not objects. Here is how the code is working now...

The user searches for 'bands' and it creates an array of all the band objects. Each band object has a bunch of posts in band.posts. So to get all the posts out of all of the bands I map through all the bands, then for each band I map through all of their posts. Each post then goes through the function 'convertPost()' to convert it into the component. I now have an array of post components. This is what I want to sort. Here is the code that does all of that -

{bandTypes === 'all' ? allBands.map(band => {
    if(band.youtube.length > 0 && band.bandBio !== 'n/a' && band.bandGenre !== 'n/a'){
        return band.posts.map(post => {
            let currPost = convertPost(post, band)
            return currPost
        })
    }
}).forEach(post => console.log(post)) : null}

I used a .forEach() to console.log each post - It returns the console.log of the react component... The date is located in props.post.date

    0:
$$typeof: Symbol(react.element)
key: "NOLA DUDES"
props:
    addFavorites: (userId, band) => {…}
    band: {quoteGenerator: Array(0), youtube: Array(1), posts: Array(2), favorites: Array(1), _id: "5eb20ce78b8cee4494eb44a0", …}
    bandBio: "This is my new band bioThis is my new band bioThis is my new band bioThis is my new band bioThis is my new band bioThis is my new band bio"
    bandName: "NOLA DUDES"
    favorites: ["5e8b54337d9c710ca6f117fa"]
    id: "5eb20ce78b8cee4494eb44a0"
    post:
        approved: null
        data: ""
        date: "2020-05-06T01:03:35.818Z"
        postId: "55445155-0690-46d4-a3bb-4cfd2ea160c3"
        rockOn: []
        type: "band"
__proto__: Object
youtube: ["4_eLn4B9MzQ"]
key: (...)
get key: ƒ ()
__proto__: Object
ref: null
type: ƒ BandCard(props)
_owner: FiberNode {tag: 0, key: null, stateNode: null, elementType: ƒ, type: ƒ, …}
_store: {validated: false}
_self: null
_source: {fileName: "/Users/NickMcLean/Desktop/REACT/AutoQuoteGenerator…t/src/components/Profile/SearchInputs/MainFeed.js", lineNumber: 209, columnNumber: 25}
__proto__: Object
1: {$$typeof: Symbol(react.element), key: null, ref: null, props: {…}, type: ƒ, …}
length: 2
__proto__: Array(0)

So I tried this... do you know how to access this date so that I can sort this array of posts by date? I know this isn't the normal way to access the props...

{bandTypes === 'all' ? allBands.map(band => {
    if(band.youtube.length > 0 && band.bandBio !== 'n/a' && band.bandGenre !== 'n/a'){
        return band.posts.map(post => {
            let currPost = convertPost(post, band)
            return currPost
        })
    }
}).sort((a, b) => b.props.post.date - a.props.post.date) : null}

I have also tried to sort the objects before doing the 'convertPost()' function... but the convert post function needs the 'band' parameter to work, which is only found in the map.

{bandTypes === 'all' ? allBands.map(band => {
    if(band.youtube.length > 0 && band.bandBio !== 'n/a' && band.bandGenre !== 'n/a'){
        return band.posts.map(post => {
            return post
        })
    }
}).sort((a, b) => b.date - a.date).forEach(post => {
    let currPost = convertPost(post, band)
    return currPost
}) : null}

Here is the convertPosts function

    const convertPost = (post, band) => {
        if(genre === 'Genre'){
            switch (post.type) {
                case "video":
                    return (
                        <VideoPosts key={post.postId} addFavorites={addFavorites} favorites={band.favorites} addRockOn={addRockOn} link={post.data} band={band} post={post} _id={band._id} />
                    )
                case "text":
                    return (
                        <FeedPosts key={post.postId} addFavorites={addFavorites} favorites={band.favorites} addRockOn={addRockOn} band={band} post={post} _id={band._id}/>
                    )   
                case "show":
                    return (
                        <ShowsPosts key={post.postId} addFavorites={addFavorites} favorites={band.favorites} addRockOn={addRockOn} band={band} post={post} _id={band._id}/>
                    )
                case "band":
                    return (
                        <BandCard id={band._id} key={band.bandName} youtube={band.youtube} bandName={band.bandName} bandBio={band.bandBio} post={post} addFavorites={addFavorites} favorites={band.favorites} band={band} />
                    )
                case 'instagram':
                    return (
                        <InstagramPosts key={post.postId} addFavorites={addFavorites} favorites={band.favorites} addRockOn={addRockOn} band={band} post={post} _id={band._id} />
                    )
                default: 
                    return null;
            }
        }else {
            if(band.bandGenre === genre ){
                switch (post.type) {
                    case "video":
                        return (
                            <VideoPosts addFavorites={addFavorites} favorites={band.favorites} addRockOn={addRockOn} link={post.data} band={band} post={post} />
                        )
                    case "text":
                        return (
                            <FeedPosts addFavorites={addFavorites} favorites={band.favorites} addRockOn={addRockOn} band={band} post={post} _id={band._id} />
                        )   
                    case "show":
                        return (
                            <ShowsPosts addFavorites={addFavorites} favorites={band.favorites} addRockOn={addRockOn} band={band} post={post} _id={band._id}/>
                        )
                    case "band":
                        return ( <BandCard id={band._id} key={band.bandName} youtube={band.youtube} bandName={band.bandName} bandBio={band.bandBio} addFavorites={addFavorites} favorites={band.favorites} band={band}/>
                        )
                    default: 
                        return null;
                }
            }
        }

    }

Post formats -

        {
            "type": "instagram",
            "data": "https://scontent-dfw5-1.xx.fbcdn.net/v/t51.2885-15/94831976_156494885869068_8673191033070945504_n.jpg?_nc_cat=103&_nc_sid=8ae9d6&_nc_ohc=BOk-_e1RMVwAX-w2ywz&_nc_ht=scontent-dfw5-1.xx&oh=f19acf2fab558ce0d2a79fba3d90db71&oe=5EE1F652",
            "link": "http://www.instagram.com/on_deband_booking",
            "date": "2020-04-28T16:32:40+0000",
            "postId": "18033963559249859",
            "rockOn": []
        },
        {
            "type": "text", //Really this is facebook
            "data": "Have you gotten that special someone, or...someone's, a valentine yet (we mean your favorite local bands)? This Valentine On DeBand is giving you a way to say thank you and show your appreciation to local bands and artists with a special gift (or you can gift it to yourself if you want, no harm in treating yo self)! Tomorrow is the big day, just follow this link: https://www.ondeband.com/happy-valentines/ \n\nDon't forget to follow us for all things music!\n*\n*\n*\n*\n#ondeband #band #music #valentines #specialsomeone #local #localmusic #localband #venue #rockshow #rock #country #metal #pop #punk #emo #love #gratitude #happyheartday",
            "link": "http://www.facebook.com/107460777308513_199513551436568",
            "date": "2020-02-13T16:14:34+0000",
            "postId": "107460777308513_199513551436568",
            "rockOn": []
        },
        {
            "type": "band",
            "data": "",
            "date": "2020-05-05T23:43:53.002Z",
            "postId": "c51295fe-14b0-4a19-9cc3-87da2a28c93f",
            "approved": null,
            "rockOn": []
        },
        {
            "type": "video",
            "data": "PuBqEdb464g",
            "date": "2020-05-05T22:40:23.958Z",
            "postId": "af28c07e-49cb-4b3c-9c6e-452112e1026a",
            "rockOn": []
        },
        {
            "date": "2020-05-05T22:54:59.673Z",
            "type": "show",
            "client": "email",
            "clientId": "5e8b54337d9c710ca6f117fa",
        }
Nick McLean
  • 601
  • 1
  • 9
  • 23

2 Answers2

0

Why not sort the objects first before mapping to post components?

{
bandTypes === "all"
  ? allBands
      .map((band) => {
        if (
          band.youtube.length > 0 &&
          band.bandBio !== "n/a" &&
          band.bandGenre !== "n/a"
        ) {
          return band.posts;
        }
      })
      .sort((a, b) => b.date - a.date)
      .map((post) => {
        let currPost = convertPost(post, band);
        return currPost;
      })
  : null;
}
richbai90
  • 4,994
  • 4
  • 50
  • 85
  • Hmm. I tried some similar things without success. The code above says "TypeError: Date(...).getTime is not a function" . Either way... wouldn't that just sort the posts of each band rather than the posts of all the bands? – Nick McLean May 12 '20 at 15:42
  • I also tried Date(a.date).getTime() - Which returns undefined. – Nick McLean May 12 '20 at 15:44
  • I don't know the format of your objects so it's possible converting to a date is the wrong way to go, but the idea is the same. I've edited my post for clarity, basically sort the objects before mapping to a component. In the edit I put the sort at the end so all the posts get sorted – richbai90 May 12 '20 at 15:52
  • I think this would work but is there a way to get the 'band' parameter form .map((band) to get to the convertPost(post, band) function? 'band' no longer exist in the scope at that point of the code. I first tried this format, but since the convertPost function needs band to run...I thought it was the wrong way to do it? – Nick McLean May 12 '20 at 15:57
  • 1
    @Adam Jeliński has the right idea. I was in the process of converting my code when I saw his answer. – richbai90 May 12 '20 at 16:02
0

What you have to do first is reduce the allBands array into an array of all the posts, without any nesting. To keep both the post and band values, you can just combine them into a single object. Then you can sort it by date, however it is expressed in your data.

Doing anything with already created components is generally a bad idea and I would discourage it.

Here's the code:

{
    bandTypes === "all"
        ? allBands
              .reduce(
                  (allPosts, band) =>
                      allPosts.concat(
                          (band.youtube.length > 0 &&
                              band.bandBio !== "n/a" &&
                              band.bandGenre !== "n/a")
                              ? band.posts.map((post) => ({ post, band }))
                              : []
                      ),
                  []
              )
              .sort((a, b) => new Date(b.post.date) - new Date(a.post.date))
              .map(({ post, band }) => convertPost(post, band))
        : null;
}

You can find more information about reduce here.

Adam Jeliński
  • 1,708
  • 1
  • 10
  • 21
  • Wow - almost there. It seems like its going to work perfectly but then when convertPost() happens it sorts the posts by the posts type... then date. For example - It sorts all the facebook posts by date, then all the instagram posts by date, then all the native posts by date. Instead of mixing and matching between the types. I'll post the convertPosts() function above – Nick McLean May 12 '20 at 16:18
  • @NickMcLean I would guess there are different date formats for each platform. Could you post some examples of what the dates looks like for each post source? – Adam Jeliński May 12 '20 at 16:43
  • I posted the different post objects above. – Nick McLean May 12 '20 at 16:55
  • .sort((a, b) => new Date(b.post.date) - new Date(a.post.date)) seems to be doing it! – Nick McLean May 12 '20 at 16:57
  • Only one more issue... the if statement from before, which worked, no longer functions how I expect it to. - if(band.youtube.length > 0 && band.bandBio !== 'n/a' && band.bandGenre !== 'n/a'){...map the posts} Now it filters out some of the bands that actually have those qualities. -- where does allPosts come from? – Nick McLean May 12 '20 at 17:09
  • Great you figured out the sorting! The problem with the `if` seems very weird, because it's exactly the same statement, just a different syntax. This must be a small issue with variables looking correct but being wrong. `allPosts` is the accumulator argument to the function that `reduce` uses. Take a look at the reference for `reduce`: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce – Adam Jeliński May 12 '20 at 17:36
  • Yeah. Its very weird what is happening - Currently, allBands is an array of 3 bands each having posts. When I run this new code it returns only the one bands posts instead of all 3 bands. – Nick McLean May 12 '20 at 17:44
  • Oh I've made quite a mistake... I'm very surprised it worked at all. You can't sum arrays together, they have to be concatenated. I'll fix my code – Adam Jeliński May 12 '20 at 17:52
  • Magic!! So if I am understanding correctly, the previous code would get the array of posts but it couldnt be summed to another array of posts - so you fixed it by concatinating them all together? – Nick McLean May 12 '20 at 17:57
  • Yes, the previous function would fail to properly join previous posts (`allPosts`) with the currently analysed ones. I was doing a bit too much Python lately, where the + operator for arrays means concatenation... – Adam Jeliński May 12 '20 at 18:00
  • Hey Adam! The sort is being a bit weird in safari - I was wondering if you could point me in the right direction? Some of the posts come from my database, and they are sorted correctly. But posts that come from the facebook api call get added to the end of my array instead of getting sorted. This only happens in safari. – Nick McLean May 15 '20 at 13:40
  • https://stackoverflow.com/questions/61821191/safari-array-sorting-by-date-doesnt-sort – Nick McLean May 15 '20 at 14:06