BARNOWL
BARNOWL

Reputation: 3589

How to show the last 2 elements of an array based on createdAt

I'm trying to show the 2 previous recent comments based on createdAt, by implementing this filterMethod

const filterComments = props.comments.slice(0, inc).sort((a, b) => {
    const date1 = new Date(a.createdAt) as any;
    const date2 = new Date(b.createdAt) as any;
    return date1 - date2;
});

inc is variable that increments if user selects showMore

which isn't anything special

  const showMoreComments = () => {
        return filterComments.map((comment, i) => (
            <div key={i}>
                <CommentListContainer comment={comment} openModal={openModal} handleCloseModal={handleCloseModal} isBold={isBold} handleClickOpen={handleClickOpen} {...props} />
            </div>
        ));
    };

The problem is if the comments has more than 2 comments, the filtering gets out of order, so by default if there just 2 comments filterComments shows the recent 2 comments which works as i expect, but if there are more than 2 comments and i click on show more comments, it stops filtering correctly.

I've tried this method arr.slice(Math.max(arr.length - 5, 1))

In a javascript array, how do I get the last 5 elements, excluding the first element?

but its not really the answer i was looking for, i think this could be a reducer issue, or something.

What could i be doing wrong

showMoreMethod

  const showComments = (e) => {
        e.preventDefault();
        if (inc + 2 && inc <= the_comments) {
            setShowMore(inc + 2);
            setShowLessFlag(true);
        } else {
            setShowMore(the_comments);
        }
    };

CommentList.tsx

import React, { Fragment, useState } from "react";
import Grid from "@material-ui/core/Grid";
import OurSecondaryButton from "../../../common/OurSecondaryButton";
import CommentListContainer from "../commentListContainer/commentListContainer";
import storeHooks from "../../../common/storeHooks";

function CommentList(props: any) {
    const [showMore, setShowMore] = useState<Number>(2);
    const [openModal, setOpenModal] = useState(false);
    const [showLessFlag, setShowLessFlag] = useState<Boolean>(false);
    const the_comments = props.comments.length;
    const inc = showMore as any;
    const min = Math.min(2, the_comments - inc);
    const showComments = (e) => {
        e.preventDefault();
        if (inc + 2 && inc <= the_comments) {
            setShowMore(inc + 2);
            setShowLessFlag(true);
        } else {
            setShowMore(the_comments);
        }
    };
    const handleClickOpen = () => {
        setOpenModal(true);
    };
    const handleCloseModal = () => {
        setOpenModal(false);
    };

    const showLessComments = (e) => {
        e.preventDefault();
        setShowMore(2);
        setShowLessFlag(false);
    };
    const isBold = (comment) => {
        return comment.userId === props.userId ? 800 : 400;
    };

    const filterComments = props.comments.slice(0, inc).sort((a, b) => {
        const date1 = new Date(a.createdAt) as any;
        const date2 = new Date(b.createdAt) as any;
        return date1 - date2;
    });

    const showMoreComments = () => {
        return filterComments.map((comment, i) => (
            <div key={i}>
                <CommentListContainer comment={comment} openModal={openModal} handleCloseModal={handleCloseModal} isBold={isBold} handleClickOpen={handleClickOpen} {...props} />
            </div>
        ));
    };

    return (
        <Grid>
            <Fragment>
                <div style={{ margin: "30px 0px" }}>
                    {props.comments.length > 2 ? (
                        <Fragment>
                            {min !== -1 ? (
                                <Fragment>
                                    {min !== 0 ? (
                                        <OurSecondaryButton onClick={(e) => showComments(e)} component="span" color="secondary">
                                            View {min !== -1 ? min : 0} More Comments
                                        </OurSecondaryButton>
                                    ) : (
                                        <OurSecondaryButton onClick={(e) => showLessComments(e)} component="span" color="secondary">
                                            Show Less Comments
                                        </OurSecondaryButton>
                                    )}
                                </Fragment>
                            ) : (
                                <OurSecondaryButton onClick={(e) => showLessComments(e)} component="span" color="secondary">
                                    Show Less Comments
                                </OurSecondaryButton>
                            )}
                        </Fragment>
                    ) : null}
                </div>
            </Fragment>
            {showLessFlag === true ? (
                // will show most recent comments below
                showMoreComments()
            ) : (
                <Fragment>
                    {/* filter based on first comment  */}
                    {filterComments.map((comment, i) => (
                        <div key={i}>
                            <CommentListContainer comment={comment} openModal={openModal} handleCloseModal={handleCloseModal} isBold={isBold} handleClickOpen={handleClickOpen} {...props} />
                        </div>
                    ))}
                </Fragment>
            )}
        </Grid>
    );
}
// prevents un-necesary re renders
export default React.memo(CommentList);

reducer Reducer that handles the new state

 case types.COMMENT_UPDATES_SUCCESS:
    console.log(action);
    const findCommentKey2 = state.posts.findIndex((x) => x.id === action.payload.comment.postId);
    console.log(findCommentKey2);
    draft.posts[findCommentKey2].Comments = [
        action.payload.comment,
        // add comment first, then sort it out by the most recent comment
        ...draft.posts[findCommentKey2].Comments,
    ];
    return;

comment shape

[
  {
    "id": 177,
    "comment_body": "",
    "gifUrl": "https://media0.giphy.com/media/LRNxdA0soqs09YWa4F/giphy.gif?cid=e8452e68d3e94d3464efb70e1059fae80209a6b531b30b7d&rid=giphy.gif",
    "userId": 9,
    "postId": 15,
    "createdAt": "2020-05-24T21:11:07.939Z",
    "updatedAt": "2020-05-24T21:11:07.939Z",
    "author": {
      "username": "barnowl",
      "gravatar": "https://api.adorable.io/avatars/400/bf1eed82fbe37add91cb4192e4d14de6.png",
      "bio": null
    }
  },
  {
    "id": 178,
    "comment_body": "",
    "gifUrl": "https://media2.giphy.com/media/xThtalTQnCNEatzgUU/giphy.gif?cid=e8452e68d3e94d3464efb70e1059fae80209a6b531b30b7d&rid=giphy.gif",
    "userId": 9,
    "postId": 15,
    "createdAt": "2020-05-24T21:11:28.971Z",
    "updatedAt": "2020-05-24T21:11:28.971Z",
    "author": {
      "username": "barnowl",
      "gravatar": "https://api.adorable.io/avatars/400/bf1eed82fbe37add91cb4192e4d14de6.png",
      "bio": null
    }
  },
  {
    "id": 179,
    "comment_body": "fsfsfssfsf",
    "gifUrl": "",
    "userId": 9,
    "postId": 15,
    "createdAt": "2020-05-24T21:12:31.920Z",
    "updatedAt": "2020-05-24T21:12:31.920Z",
    "author": {
      "username": "barnowl",
      "gravatar": "https://api.adorable.io/avatars/400/bf1eed82fbe37add91cb4192e4d14de6.png",
      "bio": null
    }
  },
  {
    "id": 175,
    "comment_body": "fsfsfsfsfsf",
    "gifUrl": "",
    "userId": 9,
    "postId": 15,
    "createdAt": "2020-05-24T21:10:56.303Z",
    "updatedAt": "2020-05-24T21:10:56.303Z",
    "author": {
      "username": "barnowl",
      "gravatar": "https://api.adorable.io/avatars/400/bf1eed82fbe37add91cb4192e4d14de6.png",
      "bio": null
    }
  },
  {
    "id": 176,
    "comment_body": "",
    "gifUrl": "https://media3.giphy.com/media/Jrl4FlTaymFFbNiwU5/giphy.gif?cid=e8452e68f6a75bf1f94a134a15ab35ff1b0a09e2d060e1da&rid=giphy.gif",
    "userId": 9,
    "postId": 15,
    "createdAt": "2020-05-24T21:11:01.152Z",
    "updatedAt": "2020-05-24T21:11:01.152Z",
    "author": {
      "username": "barnowl",
      "gravatar": "https://api.adorable.io/avatars/400/bf1eed82fbe37add91cb4192e4d14de6.png",
      "bio": null
    }
  },
  {
    "id": 180,
    "comment_body": "fssfsffsf",
    "gifUrl": "",
    "userId": 9,
    "postId": 15,
    "createdAt": "2020-05-24T21:12:58.086Z",
    "updatedAt": "2020-05-24T21:12:58.086Z",
    "author": {
      "username": "barnowl",
      "gravatar": "https://api.adorable.io/avatars/400/bf1eed82fbe37add91cb4192e4d14de6.png",
      "bio": null
    }
  }
]

Upvotes: 1

Views: 173

Answers (1)

Pablo CG
Pablo CG

Reputation: 816

Shouldn't you sort them first before actually slicing them?

You can first use slice(0) to clone the original array, as sort() sorts the elements locally (and you shouldn't do that over the state).

This works for me:

const comments = [{createdAt: '2020-01-20'},{ createdAt: '2019-01-01'},{createdAt: '2019-05-01'},{createdAt: '2019-05-06'}];

const inc = 2;

const filterComments = comments.slice(0).sort((a, b) => {
    const date1 = new Date(a.createdAt);
    const date2 = new Date(b.createdAt);
    return date2 - date1;
}).slice(0, inc);

console.log(filterComments);

Upvotes: 2

Related Questions