Prevent duplicate objects from being added to state reduction state

I have a question on how not to add duplicates to my redux store.

It should be straightforward, but for some reason I'm not trying anything to work.

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 looks something like this:

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

The problem is that in some cases, the API I'm working with sends identical messages via websocket, which means that two identical events are added to my store.

I took a lot of approaches, but can't figure out how to make this work. I tried a lot of SO answers,

+5
source share
5 answers

Why is your code not working?

Code:

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

Since you first add a new element and then filter the same element , this way it will never add a new value to the state of the reducer.


Decision:

Use # array.findIndex to check if an element already exists in the array or not, if not, just add the element, otherwise return the same state.

Write this:

 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
source

You can use Array.prototype.find () .

Example (not verified)

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

Refresh (comment by @CodingIntrigue)

You can also use Array.prototype.some () for a better approach.

 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
source

Decision:

 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); 
+1
source

You can do something like this, as the logical part ensures that you do not get the same record twice.

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

You need to be careful when using arrays in gearboxes. Essentially, you add more items to the list when you call:

 [...state, action.event] 

If you use a card, then you can prevent duplicates

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

Source: https://habr.com/ru/post/1272009/


All Articles