#javascript #reactjs #redux
#javascript #reactjs #redux
Вопрос:
Мои редукторы Redux получают сообщения из api, и я сохраняю их в хранилище как объект для хранения сообщений по их 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
}
}))
}
Проблема в том, что я получаю сообщения, отсортированные от самого высокого идентификатора к самому низкому, но при присвоении состояния они сортируются от самого низкого идентификатора к самому высокому, что приводит к тому, что самый старый пост отображается первым, а последний — последним.
Я знаю, что если я сохраню их в массиве, проблема будет решена, но мне нужны их идентификаторы, чтобы упростить мутации. Итак, как я могу преодолеть эту проблему?
P.S: Я пробовал что-то подобное, но это не сработало =>
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. Я бы рекомендовал отсортировать сообщение по дате (я предполагаю, что сообщение содержит данные создания) или отсортировать по идентификатору в обратном порядке в селекторе вместо сохранения несериализуемого объекта Map в хранилище redux.
Ответ №1:
Порядок итерации объектов обычно соответствует порядку вставки. Однако для числовых ключей он числовой. Поскольку ваши идентификаторы записей являются числовыми, это становится порядком итерации (т. Е. От наименьшего к большему).
Вместо этого вы можете создать карту, которая гарантирует порядок вставки.
Там, где вы инициализируете карту, вместо items: {}
того, чтобы делать items: new Map()
. Когда вы добавляете элемент, вы бы сделали items.set(post.id, post)
. Вы все равно можете обращаться к ним напрямую ( items.get(3)
), а также выполнять итерации по ним ( items.forEach( item => {...} )
) в том порядке, в котором вы их вставили.
Редактировать
Согласно комментарию ниже, не рекомендуется хранить карту в хранилище redux. Ссылка, приведенная в комментарии, говорит, что все в порядке, если вы не заботитесь о постоянстве и отладке во времени, но это справедливое замечание. Тогда более естественным решением с учетом этого было бы сохранить результаты в виде массива (что, по словам OP, они не хотели делать).
Операция индексации отрицательных чисел, описанная ниже, умна, но немного сложна. Вы также можете просто сделать индексы не похожими на числа, т. Е.
draft.posts[`post-${post.id}`]
Другой вариант — разрешить их сортировку в том виде, в каком они уже есть, но при доступе к ним просматривайте их в обратном порядке.
Комментарии:
1. Настоятельно рекомендуется помещать в хранилище только простые сериализуемые объекты, массивы и примитивы. Ваше решение может сломать инструменты redux dev и сохранить и, вероятно, многие другие промежуточные программы или расширения для redux.
Ответ №2:
Поскольку оптимальным решением является приведенное выше, я нашел небольшой ответ на этот вопрос:
Как tmdesigned
уже упоминалось, числовые ключи, отсортированные от младшего к старшему, мы можем добавлять -
перед числами, чтобы порядок итераций стал обратным.
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
}
}))
}