Ich habe eine Frage zum Verhindern, dass Duplikate zu meinem Redux-Shop hinzugefügt werden.
Es sollte einfach sein, aber aus irgendeinem Grund funktioniert nichts, was ich versuche.
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;
}
};
Die action
sieht ungefähr so aus:
{
type: "ADD_EVENT",
event: { event_id: 1, name: "Chelsea v Arsenal" }
}
Das Problem ist, dass die API, mit der ich arbeite, gelegentlich identische Nachrichten über einen Websocket sendet, was bedeutet, dass zwei identische Ereignisse zu meinem Shop hinzugefügt werden.
Ich habe viele Ansätze verfolgt, kann aber nicht herausfinden, wie dies funktioniert. Ich habe viele SO Antworten ausprobiert.
Warum schlägt Ihr Code fehl?
Code:
return [...state, action.event].filter(ev => {
if(ev.event_id !== action.event.event_id){
return ev;
}
});
Da Sie zuerst das neue Element hinzufügen und dann das selbe Element filtern, wird auf diese Weise niemals der neue Wert im Reduzierungsstatus hinzugefügt.
Lösung:
Verwenden Sie # array.findIndex , um zu überprüfen, ob das Element bereits im Array vorhanden ist oder nicht, und fügen Sie dann nur das Element hinzu, ansonsten wird derselbe Status zurückgegeben.
Schreiben Sie es so:
case "ADD_EVENT":
let index = state.findIndex(el => el.event_id == action.event.event_id);
if(index == -1)
return [...state, action.event];
return state;
Lösung:
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;
}
};
Prüfung:
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);
Sie können Array.prototype.find () verwenden.
Beispiel (nicht getestet)
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 (@ CodingIntrigues Kommentar)
Sie können für einen besseren Ansatz auch Array.prototype.some () verwenden
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;
}
};
Sie können so etwas tun, damit der logische Teil sicherstellt, dass Sie nicht zweimal denselben Eintrag erhalten.
const x = filter.arrayOfData(item => item.event_id !== EVENT_FROM_SOCKET);
if (x.length === 0) {
// dispatch action here
} else {
// ignore and do nothing
}
Sie müssen vorsichtig sein, wenn Sie Arrays in Reduzierungen verwenden. Sie fügen der Liste im Wesentlichen weitere Elemente hinzu, wenn Sie anrufen:
[...state, action.event]
Wenn Sie stattdessen eine Karte verwenden, können Sie Duplikate vermeiden
const events = { ...state.events }
events[action.event.event_id] = action.event.name]
{...state, events }