防止将重复的对象添加到 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(状态)-将生命周期方法添加到类中

React Js,将新对象添加到数组中[重复]

React Typescript - 在路由中传递时如何将类型添加到 location.state

React JS - 如何在对象内添加对象