1
votes

I'm new to react but I'm facing a small issue. I'm building up a social platform for practice where user's are able to post, like and comment. I'm using Change stream and socket.io to detect any changes in my database.

Everything works perfectly fine but what I'd like to know is, that when I create a post I'd like the state that has been set to be sorted via date before mapping through the posts. knowing that when the useEffect is triggered the data retrieved would be sorted by date instead of scrolling all the way down to the new post created.

Here is my code snippet. I've tried different ways to sorting but unfortunately I'm unable to achieve it. I'd like the posts to be sorted by date when re-rendered to be displayed if that make sense.

const [posts, setPosts] = useState([]);

useEffect(() => {
    const handler = (item) => {
         setPosts((oldPosts) => [...oldPosts.filter(p => p._id !== item._id), item]);
    };
    socket.on('posts', handler);
    return () => socket.off('posts', handler);
}, []);
2
When a new post created and you retrieved it from socket you should add it to first element of posts array because it's the newest one. I think there is no need to sort. Maybe I don't understand what you want exactly.Nima Ebrazeh
@NimaEbrazeh What I actually want is that every time I create, like or comment on a post or any changes occur on the post, I always want to make sure that the order of the posts displayed in the UI are sorted by the date posted (posts.postedOn). What you mentioned slightly worked, but once I liked the post or any changes occur it seems to lose order, so I'd always like to ensure that the posts are sorted no matter the changes made, thus not effecting the UI, is that abit more clear?MuddledRanger 21

2 Answers

0
votes

Well actually we have two possibility:

1- updated item is new. So put it at first index of array.

2- updated item is duplicate. Then just update it's value using map.

const handler = (item) => {
    setPosts((oldPosts) => {
        const findItem = oldPosts.find((post) => post._id === item._id);
        if (findItem) {
          return oldPosts.map((post) => (post._id === item._id ? item : post));
        } else {
          return [item, ...oldPosts];
        }
    });
};

Be aware that in this method you should sort posts on the first render of the component by Date.

0
votes

All you need to do is run this code before setPosts and pass date sorted array to setPosts by using the following code.

yourArray.sort(function (a, b) {
  // Turn your strings into dates, and then subtract them
  // to get a value that is either negative, positive, or zero.
  return new Date(b.date) - new Date(a.date);
});