Лучший способ изменить порядок списка в реальном времени в React-Redux?

В настоящее время я создаю приложение со списком в реальном времени. вид списка как на картинке ниже: Лучший способ изменить порядок списка в реальном времени в React-Redux?

Этот список будет обновляться в реальном времени при срабатывании одного из следующих действий:

  • Сообщение обновлено, значение updated_time будет изменено.
  • Получите новое сообщение
  • Получить статус непрочитанного сообщения

Поэтому я хочу отсортировать этот список по двум условиям:

  1. Все unRead_message всегда вверху
  2. Все сообщения должны быть отсортированы по обновленному_времени DESC (сначала самые новые), кроме unread_message всегда в приоритетах.

Данные этого списка контролируются этими редукторами:

    export const data = createReducer(
    {},
    {
        [ CONVERSATIONS_RECEIVE ]: ( state, { conversations } ) => {
            return reduce(
                conversations,
                ( memo, conversation ) => {
                    const { id } = conversation.data;

                    if ( memo === state ) {
                        memo = { ...memo };
                    }

                    memo[ id ] = conversation;
                    return memo;
                },
                state
            );
        },
        [ RECEIVED_PENDING_MESSAGE ]: ( state, { data } ) => {

            if ( !data || !data.conversation_id in state ) return state;

            return update( state, {
                [ data.conversation_id ]: { data: { $merge: { snippet: data.message, updated_time: data.created_time } } }
            } )
        },
        [ RECEIVED_CONVERSATION_SEEN ]: ( state, { data } ) => {
            if ( !data || !data.conversation_id in state ) return state;

            return update( state, {
                [ data.conversation_id ]: { data: { $merge: { seen: true } } }
            } )
        },
        [ RECEIVED_CONVERSATION_UNSEEN ]: ( state, { data } ) => {
            if ( !data || !data.conversation || !data.conversation.id in state ) return state;

            return update( state, {
                [ data.conversation.id ]: { data: { $merge: { seen: false } } }
            } )
        },
    }
);

export function keys( state = [], action ) {
    switch ( action.type ) {
        case CONVERSATIONS_RECEIVE:
            if ( !action.conversations || !action.conversations.length ) return state;
            return state.concat( action.conversations.map( conversation => conversation.data.id ) );
        default:
    }

    return state;
}

export default combineReducers( {
    keys,
    data,
    isRequesting,
} );

Данные списка, отображаемые массивом ключей:

[
  "id_1",
  "id_2",
  //....
]

и данные:

[
    {
        "data": {
            "can_comment": false,
            "can_hide": false,
            "can_like": false,
            "can_reply": true,
            "can_reply_privately": false,
            "comment_id": "",
            "id": "hbiocjgwxpncbnja8a3rra4oke",
            "is_hidden": false,
            "is_private": false,
            "last_seen_by": "ckj7mny56jrmir4df8h466uk7a",
            "message": "",
            "page_id": "1651651651651651",
            "post_id": "",
            "private_reply_conversation": "null",
            "scoped_thread_key": "t_1221211454699392",
            "seen": true,
            "snippet": "? [ TRI ÂN VÀNG-NGÀN ƯU ĐÃI ] ?\nMiễn phí ship tận nhà ???\nChỉ còn 350k trọn bộ COMBO 3 sản phẩm tuyệt vời cho chị em và các bé nhà mình : \n? Vòng tay chỉ đỏ kim vàng đính đá topaz được nhập từ Thái Lan \n? Dây chuyền hồ ly hợp mệnh \n? Vòng tay dâu tằm cho bé \nKhuyến mại chỉ áp dụng với những khách hàng đáng yêu nhận được tin nhắn này.Nhanh tay để lại SỐ ĐIỆN THOẠI để được thỉnh bộ sản phẩm với giá siêu khuyến mại này Chị  Chị Hai nha ???",
            "type": "message",
            "unread_count": 0,
            "updated_time": "2018-12-07T12:00:21+0000"
        },
        "tags": [],
        "from": {
            "id": "1223645637789307",
            "name": "Chị Hai"
        }
    },
    {
        "data": {
            "can_comment": false,
            "can_hide": false,
            "can_like": false,
            "can_reply": true,
            "can_reply_privately": false,
            "comment_id": "",
            "id": "7oemjmkpxidi7cgk99ggbdamdw",
            "is_hidden": false,
            "is_private": false,
            "last_seen_by": "ckj7mny56jrmir4df8h466uk7a",
            "message": "",
            "page_id": "1651651651651651",
            "post_id": "",
            "private_reply_conversation": "null",
            "scoped_thread_key": "t_279998559200944",
            "seen": true,
            "snippet": "Giá hơi cao",
            "type": "message",
            "unread_count": 0,
            "updated_time": "2018-12-07T12:00:19+0000"
        },
        "tags": [],
        "from": {
            "id": "280004999200300",
            "name": "Chung Ngoc"
        }
    },
    // ..... other items
]

Я пытался:

function mysortfunction(a, b) {

    // always sort by updated_time first
    if ( a.data.updated_time > b.data.updated_time ) return 1;
    if ( a.data.updated_time <= b.data.updated_time ) return -1;

    // if BOTH a.seen == false AND b.seen == false, we'll sort a & b by updated_time
    if ( !a.data.seen && !b.data.seen ) {
        if ( a.data.updated_time > b.data.updated_time ) return 1;
        if ( a.data.updated_time <= b.data.updated_time ) return -1;
    }

    return 0;
}

Может ли кто-нибудь сказать мне, как лучше всего отсортировать этот список на основе моих условий выше, большое спасибо!

вы пробовали что-нибудь, чтобы их отсортировать?

Doğancan Arabacı 13.12.2018 09:18

Пожалуйста, взгляните на мой другой ответ. Это дает образец того, как обрабатывать динамические дочерние элементы из магазина. Это может дать вам полезные данные: stackoverflow.com/questions/53189290/…

gazdagergo 13.12.2018 09:35

@ DoğancanArabacı: извините, я отредактировал свой вопрос, чтобы показать, что я пробовал!

Enesy 13.12.2018 09:39
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
2
3
398
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Я не читал четко весь ваш код, но вы можете переупорядочить свой список только с помощью функций javascript, вы будете использовать метод sort () для сортировки всего вашего списка по updated_time и просмотренному или not_seen, вам нужно добавить функцию для метода сортировки , но единственная проблема заключается в том, что переданной функции для сравнения требуется значение типа int в качестве результата, см. их эта ссылка. так, чтобы сделать трюк, при выполнении сравнения, если его сообщение не море, добавьте, например, к UPDATED_TIME +1000000000. И так все невидимые сообщения будут первыми, и все ваши сообщения сортируются с помощью одной функции

Пара комментариев; 1. Это редуктор redux, поэтому вы не хотите мутировать, прежде чем вы сможете использовать функцию мутации sort, вам нужно сделать копию, например: arr.slice().sort(... 2. Даты представляют собой строки дат ISO, поэтому вы можете использовать сравнение строк: a.localeCompare(b) . 3. Если вы хотите выполнить сортировку по нескольким столбцам, вы можете использовать массив функций сравнения и сделать так, чтобы более ранние функции имели более высокий приоритет (запускать более позднюю функцию только в том случае, если текущая функция возвращает 0). Полный код см. В моем ответе.

HMR 13.12.2018 09:55

да, говоря от имени mutatung, мы также можем использовать оператор распространения, я не хочу говорить о том, что он использует, или, если это сокращение или нет, я просто не хотел предложить ему способ сортировки, вот и все. И когда я ответил, он не указал формат данных, поэтому я просто предположил, что это была метка времени, и если это была метка времени, я дал ему более простую и ленивую вещь, чтобы провести сравнение без необходимости использовать массив функция сравнения. Спасибо за ваш комментарий

G. Adnane 14.12.2018 22:41

Проблема, с которой я столкнулся с решением UPDATED_TIME +1000000000 для сортировки по невидимому, а затем по времени обновления, заключается в том, что ваша функция сортировки делает слишком много, функции должны реализовывать только одну вещь, и если функция делает больше, чем это, она должна вызывать другие функции, которые реализуют это или вы получите функции, которые нельзя использовать повторно и комбинировать с такими именами, как sortByUnseenAndThenByDate. Если вы видите функции с такими именами, которые реализуют что-то, а не вызывают другие функции, значит, вы делаете что-то не так.

HMR 17.12.2018 09:24

Нет, вы не поняли функцию, я не буду сортировать по невидимым, а затем обновлять, я буду сортировать один и только один раз, потому что при добавлении +1000000000 к UPDATED_TIME к невидимым элементам, когда вы выполняете сортировку, у вас автоматически будет неотправленное сообщение вверху, остальные внизу и, конечно же, все отсортированные элементы. В любом случае спасибо за ваши рекомендации

G. Adnane 17.12.2018 14:44
Ответ принят как подходящий

Вы можете отсортировать по нескольким значениям следующим образом:

const data = [
  { seen: true, updated_time: 'A' },
  { seen: true, updated_time: 'A' },
  { seen: false, updated_time: 'A' },
  { seen: false, updated_time: 'A' },
  { seen: false, updated_time: 'B' },
];
//compare booleans, returns -1,0 or 1
const compareSeen = (direction) => (a, b) =>
  a.seen === b.seen
    ? 0
    : a.seen
      ? -1 * direction
      : 1 * direction;
//compare strings, returns -1, 0 or 1
const compareDate = (direction) => (a, b) =>
  a.updated_time.localeCompare(b);

//pass array of compare functions and return a function that takes
//  a and b and keeps using compare functions until one of them returns non zero
const createSort = (comparers = []) => (a, b) =>
  comparers.reduce(
    (result, compareFn) =>
      result === 0 ? compareFn(a, b) : result,
    0,
  );
console.info(
  data
    .slice() //sort will mutate, we don't want that so we make a copy first
    .sort(createSort([compareSeen(-1), compareDate(1)])),
);

Если у вас есть время ISO из разных часовых поясов, вы не можете использовать сравнение строк, но должны сначала сопоставить строки даты с числами, а затем сопоставить их обратно:

const data = [
  { seen: true, updated_time: '2018-12-07T12:00:21+0000' },
  { seen: true, updated_time: '2018-12-07T12:00:21+0000' },
  { seen: false, updated_time: '2018-12-07T12:00:21+0000' },
  { seen: false, updated_time: '2018-12-07T12:00:21+0000' },
  { seen: false, updated_time: '2018-12-07T12:00:21+0100' },
];
//compare booleans, returns -1,0 or 1
const compareSeen = (direction) => (a, b) =>
  a.seen === b.seen
    ? 0
    : a.seen
      ? -1 * direction
      : 1 * direction;
//compare numbers, returns negative number, 0 or positive number
const compareDate = (direction) => (a, b) =>
  (a.updated_time - b.updated_time) * direction;

//pass array of compare functions and return a function that takes
//  a and b and keeps using compare functions until one of them returns non zero
const createSort = (comparers = []) => (a, b) =>
  comparers.reduce(
    (result, compareFn) =>
      result === 0 ? compareFn(a, b) : result,
    0,
  );
console.info(
  data
    .map((item) => ({
      ...item,
      updated_time: new Date(item.updated_time).getTime(),
    })) //map already copied data so sort will not mutate it
    .sort(createSort([compareSeen(-1), compareDate(-1)]))
    .map((item) => ({
      ...item,
      updated_time: new Date(
        item.updated_time,
      ).toISOString(),//note: now you have strings in UTC/Zulu time
    })),
);

Большое вам спасибо! Ваш ответ почти исправляет мой случай, за исключением того, что эти элементы не видны (visible = true), этот фрагмент не сортирует все элементы, если они видны (visible = true)

Enesy 01.03.2019 08:35

@Enesy, вы уверены, что свойство seen всегда истинно или ложно, а не undefined, null или 0? createSort([compareSeen(-1), compareDate(-1)]) означает, что он будет сортировать элементы с seen на ложный кулак (если вы используете compareSeen(1), сначала будет истина). Если оба видимых элемента одинаковы, то сначала выполняется сортировка по самой высокой дате (compareDate (1) сначала помещает самую низкую дату).

HMR 01.03.2019 13:12

Другие вопросы по теме