防止将重复的对象添加到 state react redux
Posted
技术标签:
【中文标题】防止将重复的对象添加到 state react redux【英文标题】:prevent duplicate objects being added to state react redux 【发布时间】:2018-03-02 17:28:59 【问题描述】:我有一个关于防止将重复项添加到我的 redux 商店的问题。
这应该是直截了当的,但由于某种原因,我尝试的任何方法都不起作用。
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 会通过 websocket 发送相同的消息,这意味着两个相同的事件被添加到我的商店中。
我采取了很多方法,但无法弄清楚如何让它发挥作用。我已经尝试了很多这样的答案,
【问题讨论】:
添加您尝试过的内容是没有得到无用答案的关键。 【参考方案1】:为什么你的代码失败了?
代码:
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;
【讨论】:
在我的购物车中,我有一件商品,其中一件包含数量,如果我将相同的商品添加到购物车中,我希望只增加数量item1 => quantity x2
并避免重复【参考方案2】:
解决办法:
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】:您可以使用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 的评论)
您也可以使用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;
;
【讨论】:
这是我要采取的方法。除了我将find
替换为some
@CodingIntrigue 谢谢你的补充。我更新了答案。
@CodingIntrigue 你能解释一下为什么应该使用some
而不是find
吗?【参考方案4】:
在 reducer 中使用数组时需要小心。当您调用时,您实际上是在向列表中添加更多项目:
[...state, action.event]
如果您改为使用地图,则可以防止重复
const events = ...state.events
events[action.event.event_id] = action.event.name]
...state, events
【讨论】:
好的,你在哪里用过地图?我认为传播运算符不会改变数组?这个答案似乎也暗示这就是你更新数组的方式 - ***.com/questions/37932742/…【参考方案5】:对于逻辑部分,您可以这样做,以确保您不会两次获得相同的条目。
const x = filter.arrayOfData(item => item.event_id !== EVENT_FROM_SOCKET);
if (x.length === 0)
// dispatch action here
else
// ignore and do nothing
【讨论】:
以上是关于防止将重复的对象添加到 state react redux的主要内容,如果未能解决你的问题,请参考以下文章
防止coffeescript方法将新元素添加到调用它的变量中[重复]
React/Redux - 使用扩展运算符将对象添加到数组的开头
react篇章-React State(状态)-将生命周期方法添加到类中