防止重复对象被添加到状态react redux

时间:2017-09-21 11:20:54

标签: javascript reactjs ecmascript-6 redux react-redux

我有一个关于防止将重复项添加到我的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答案,

5 个答案:

答案 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 }