我有一个关于防止将重复项添加到我的redux商店的问题。
它应该是直截了当的,但出于某种原因,我尝试的不是工作。
constructor(mdIconRegistry: MdIconRegistry, sanitizer: DomSanitizer) {
mdIconRegistry
.addSvgIcon('thumb-up', sanitizer.bypassSecurityTrustResourceUrl('./assets/thumbup-icon.svg'))
}
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
问题在于,我正在使用的API通过websocket发送相同的消息,这意味着我的商店会添加两个相同的事件。
我采取了很多方法,但无法弄清楚如何让它发挥作用。我尝试过很多SO答案,
答案 0 :(得分:3)
为什么您的代码失败了?
<强>代码:强>
return [...state, action.event].filter(ev => {
if(ev.event_id !== action.event.event_id){
return ev;
}
});
因为首先要添加新元素,然后过滤相同元素,这样它就永远不会在reducer状态下添加新值。
<强>解决方案:强>
使用#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;
答案 1 :(得分:2)
您可以使用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;
}
};
更新 (@ CodingIntrigue&#39>
您还可以使用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;
}
};
答案 2 :(得分:1)
解决方案:
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);
答案 3 :(得分:0)
你可以这样,逻辑部分确保你不会两次获得相同的条目。
const x = filter.arrayOfData(item => item.event_id !== EVENT_FROM_SOCKET);
if (x.length === 0) {
// dispatch action here
} else {
// ignore and do nothing
}
答案 4 :(得分:0)
在Reducer中使用Arrays时需要小心。当您致电时,您实际上是在列表中添加更多项目:
[...state, action.event]
如果您改为使用地图,则可以防止重复
const events = { ...state.events }
events[action.event.event_id] = action.event.name]
{...state, events }