it-roy-ru.com

не допускать повторения объектов в состояние, чтобы отреагировать

У меня есть вопрос относительно предотвращения добавления дубликатов в мой магазин редуксов.

Это должно быть прямо вперед, но по какой-то причине я ничего не пытаюсь работать.

export const eventReducer = (state = [], action) => {

    switch(action.type) {

        case "ADD_EVENT":

            return [...state, action.event].filter(ev => {
                if(ev.event_id !== action.event.event_id){
                   return ev;
                }
            });


        default:
            return state;

    }

};

action выглядит примерно так:

{
   type: "ADD_EVENT",
   event: { event_id: 1, name: "Chelsea v Arsenal" }
}

Проблема в том, что в некоторых случаях API, с которым я работаю, отправляет идентичные сообщения через веб-сокет, что означает, что два идентичных события добавляются в мой магазин.

Я использовал много подходов, но не могу понять, как заставить это работать. Я перепробовал много SO ответов,

6
user7597670

Почему ваш код не работает?

Код:

return [...state, action.event].filter(ev => {
    if(ev.event_id !== action.event.event_id){
       return ev;
    }
});

Поскольку сначала вы добавляете новый элемент, а затем фильтруете same element, таким образом он никогда не добавит новое значение в состояние редуктора.


Решение:

Используйте # array.findIndex , чтобы проверить, существует ли элемент в массиве или нет, если нет, то только добавьте элемент, в противном случае верните то же состояние.

Напишите это так:

case "ADD_EVENT":

    let index = state.findIndex(el => el.event_id == action.event.event_id);

    if(index == -1)
        return [...state, action.event];
    return state;
3
Mayank Shukla

Решение: 

const eventReducer = ( state = [], action ) => {
    switch (action.type) {
        case 'ADD_EVENT':
            return state.some(( { event_id } ) => event_id === action.event.event_id)
                ? state
                : [...state, action.event];
        default:
            return state;
    }
};

Тестовое задание:

const state1 = eventReducer([], {
    type: 'ADD_EVENT',
    event: { event_id: 1, name: 'Chelsea v Arsenal' }
});

const state2 = eventReducer(state1, {
    type: 'ADD_EVENT',
    event: { event_id: 2, name: 'Chelsea v Manchester' }
});

const state3 = eventReducer(state2, {
    type: 'ADD_EVENT',
    event: { event_id: 1, name: 'Chelsea v Arsenal' }
});

console.log(state1, state2, state3);
1
Ivan Nikitovic

Вы можете использовать Array.prototype.find () .

Пример _ ​​(Не проверено)

const eventExists = (events, event) => {
  return evets.find((e) => e.event_id === event.event_id);
}
export const eventReducer = (state = [], action) = > {
    switch (action.type) {
    case "ADD_EVENT":
      if (eventExists(state, action.event)) {
        return state;
      } else {
        return [...state, action.event];
      }
    default:
        return state;
    }
};

Update _ ​​(@ комментарий CodingIntrigue)

Вы также можете использовать Array.prototype.some () для лучшего подхода

const eventExists = (events, event) => {
  return evets.some((e) => e.event_id === event.event_id);
}
export const eventReducer = (state = [], action) = > {
    switch (action.type) {
    case "ADD_EVENT":
      if (eventExists(state, action.event)) {
        return state;
      } else {
        return [...state, action.event];
      }
    default:
        return state;
    }
};
1
bennygenel

Вы можете что-то вроде этого, чтобы логическая часть гарантировала, что вы не получите одну и ту же запись дважды.

const x = filter.arrayOfData(item => item.event_id !== EVENT_FROM_SOCKET);
if (x.length === 0) {
  // dispatch action here
} else {
  // ignore and do nothing
}
0
Adeel Imran

Вы должны быть осторожны при использовании массивов в редукторах. По сути, вы добавляете больше элементов в список, когда звоните:

[...state, action.event]

Если вы вместо этого используете карту, то вы можете предотвратить дубликаты

const events = { ...state.events }
events[action.event.event_id] = action.event.name]
{...state, events }
0
Peter