2

My Redux reducers receive posts from api and I store them in the store as object to store posts by their id's.

reducer.js

const initialState = {
    posts: {},
    postsByCategory: {},
    addingPost: false,
}
export function posts(state = initialState, action){
    enableES5()
    return(        
        produce(state, draft => {
            switch (action.type) {
                case GET_POSTS:
                    action.payload.map(post => {
                        draft.posts[post.id] = post
                    })
                    break
                default:
                    return draft
            }
        }))
    }

posts

The problem is I get the posts as sorted from highest id to lowest but while assigning to state, they become sorted from lowest id to highest which causes oldest post to seen at first and latest post at last.

I know if I store them in an array the problem will be solved but I need by their id's to make mutations easier. So how can I overcome this issue?

P.S: I tried something like this, but it didn't work =>

export function postsByIndex(state=[], action){
    enableES5()
    return(
        produce(state, draft => {
            switch(action.type){
                case GET_POSTS:
                    draft = posts(state.posts, action)
                default:
                    return draft
            }
        })
    ) 
}
1
  • 1
    I'd recommend getting the post sorted by date (I assume post has a creaton data) or sorted by id in reverse in the selector instead of storing a non serializable Map object in redux store. Commented Oct 27, 2020 at 12:02

2 Answers 2

2

The iteration order of objects is usually by the insertion order. However, for number-like keys, it is numeric. Since your post IDs are numeric, this becomes the iteration order (i.e. lowest to higher).

You can instead create a Map which guarantees insertion order.

Where you initialize the Map, instead of items: {} you would do items: new Map(). When you add an item, you would do items.set(post.id, post). You can still access them directly (items.get(3)) and also iterate through them (items.forEach( item => {...} )) in the order you inserted them.

EDIT

Per comment below, it is not recommended to store a Map in a redux store. The link shared in the comment says its fine if you don't care about persistence and time-travel debugging, but it's a fair point. A more natural solution with that in mind, then, would be to store the results as an array (which the OP said they did not want to do).

The negative number indexing OP shared below is clever, but a little hacky. You could also just make the the indices be not number-like, i.e.

draft.posts[`post-${post.id}`]

The other option is to allow them to be sorted as they already are, but when accessing them go through them in reverse.

Sign up to request clarification or add additional context in comments.

1 Comment

It is highly recommended that you only put plain serializable objects, arrays, and primitives into your store. Your solution can break redux dev tools and persist and probably many other middleware or extensions to redux.
0

As the optimal solution is the above one, I found a little hack to this question:

As tmdesigned mentioned, number-like keys sorted from lowest to highest, we can add - to front of numbers so iteration order becomes reversed.

export function posts(state = initialState, action){
    enableES5()
    return(        
        produce(state, draft => {
            const postId = -(action.postId)            
            switch (action.type) {
                case GET_POSTS:
                    action.payload.map(post => {
                        draft.posts[-post.id] = post
                    })
                    break
                default:
                    return draft
            }
        }))
    }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.