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

Я сейчас создаю приложение со списком в реальном времени.вид списка в виде рисунка ниже: enter image description here

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

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

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

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

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

    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
]

Iпопробовал:

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;
}

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

Ответы [ 2 ]

0 голосов
/ 13 декабря 2018

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

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.log(
  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.log(
  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
    })),
);
0 голосов
/ 13 декабря 2018

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...