2017-09-21 71 views
5

Mam pytanie dotyczące zapobiegania dodawaniu duplikatów do mojego sklepu redux.zapobiec duplikowaniu obiektów dodawanych do stanu reagx redux

To powinno być proste, ale z jakiegoś powodu nic nie próbuję działa.

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 wygląda coś jak poniżej:

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

Problem jest, że czasami API Pracuję z wysyła ponad identyczne wiadomości przez websocket, co oznacza, że ​​dwa identyczne zdarzenia są dodawanie do mojego sklepu.

Podjęłam wiele podejść, ale nie mogę wymyślić, jak to zrobić. Próbowałem wielu odpowiedzi SO,

+0

Dodawanie czego próbowaliśmy jest kluczowym punktem nie uzyskanie nie użytecznych odpowiedzi. – bennygenel

Odpowiedz

3

Dlaczego kod nie działa?

Kod:

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

Ponieważ pierwszy dodajesz nowy element, a następnie przefiltrowanie sam element, w ten sposób nigdy nie będzie dodać nową wartość w stanie reduktora.


Rozwiązanie:

Zastosowanie #array.findIndex, by sprawdzić, czy element istnieje w tablicy lub nie, jeśli nie, to tylko dodać element inaczej wrócić tego samego państwa.

napisać to tak:

case "ADD_EVENT": 

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

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

Możesz coś takiego, dla części logiki, aby upewnić się, że nie otrzymasz dwa razy tego samego wpisu.

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

Należy zachować ostrożność podczas używania tablic w reduktorach. To w gruncie dodając kolejne elementy do listy podczas rozmowy:

[...state, action.event] 

Jeśli zamiast korzystać z mapy, a następnie można zapobiec duplikaty

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

ok, gdzie użyłeś tutaj mapy? i myślałem, że operator rozprzestrzeniania się nie mutuje macierzy? również ta odpowiedź wydaje się zasugerować, w jaki sposób chcesz zaktualizować tablicę - https://stackoverflow.com/questions/37932742/redux-how-to-add-entry-to-array-in-reducer –

1

Można użyć Array.prototype.find().

Przykład(nie badane)

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

Aktualizacja(@ komentarz CodingIntrigue za)

Można również użyć Array.prototype.some() dla lepszego podejścia

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

To jest podejście, które wziął. Oprócz tego, że zamieniłbym 'find' na [niektóre] (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/some) – CodingIntrigue

+0

@CodingIntrigue dziękuję za dodanie. Zaktualizowałem odpowiedź. – bennygenel

1

Rozwiązanie:

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

Test:

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