2017-09-21 22 views
5

Tôi có một câu hỏi liên quan đến việc ngăn các bản sao bị thêm vào kho lưu trữ Redux của tôi.ngăn các đối tượng trùng lặp được thêm vào trạng thái phản ứng redux

Nó nên thẳng về phía trước nhưng vì một lý do nào đó tôi không thử làm việc.

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; 

    } 

}; 

Các action trông giống như dưới đây:

{ 
    type: "ADD_EVENT", 
    event: { event_id: 1, name: "Chelsea v Arsenal" } 
} 

Vấn đề là vào những dịp API tôi đang làm việc với được gửi qua tin nhắn giống hệt thông qua một WebSocket, có nghĩa là hai sự kiện giống hệt nhau được thêm vào cửa hàng của tôi.

Tôi đã thực hiện nhiều cách tiếp cận nhưng không thể tìm ra cách để làm việc này. Tôi đã thử nhiều câu trả lời cho SO,

+0

Thêm những gì bạn đã cố gắng là điểm mấu chốt của việc không nhận được câu trả lời không hữu ích. – bennygenel

Trả lời

3

Tại sao mã của bạn không thành công?

Code:

return [...state, action.event].filter(ev => { 
    if(ev.event_id !== action.event.event_id){ 
     return ev; 
    } 
}); 

Bởi vì đầu tiên bạn đang thêm các yếu tố mới sau đó lọc cùng yếu tố, bằng cách này nó sẽ không bao giờ thêm giá trị mới trong tình trạng giảm tốc.


Giải pháp:

Sử dụng #array.findIndex để kiểm tra xem mục đã tồn tại trong mảng hay không nếu không thì chỉ làm tăng thêm yếu tố khác trở lại tình trạng tương tự.

Viết nó như thế này:

case "ADD_EVENT": 

    let index = state.findIndex(el => el.event_id == action.event.event_id); 

    if(index == -1) 
     return [...state, action.event]; 
    return state; 
0

Bạn có thể như thế này, đối với phần logic để đảm bảo bạn không nhận được cùng một mục nhập hai lần.

const x = filter.arrayOfData(item => item.event_id !== EVENT_FROM_SOCKET); 
if (x.length === 0) { 
    // dispatch action here 
} else { 
    // ignore and do nothing 
} 
0

Bạn cần phải cẩn thận khi sử dụng Mảng trong bộ giảm tốc. về cơ bản bạn đang bổ sung thêm mặt hàng vào danh sách khi bạn gọi:

[...state, action.event] 

Nếu bạn thay vì sử dụng một bản đồ sau đó bạn có thể ngăn bản sao

const events = { ...state.events } 
events[action.event.event_id] = action.event.name] 
{...state, events } 
+0

ok, ở đâu bạn đã sử dụng bản đồ ở đây? và tôi nghĩ rằng các nhà điều hành lây lan doesnt mutate mảng? cũng câu trả lời này dường như đề nghị đây là cách bạn sẽ cập nhật mảng - https://stackoverflow.com/questions/37932742/redux-how-to-add-entry-to-array-in-reducer –

1

Bạn có thể sử dụng Array.prototype.find().

Ví dụ(Không kiểm tra)

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; 
    } 
}; 

Cập nhật(@ CodingIntrigue của bình luận)

Bạn cũng có thể sử dụng Array.prototype.some() cho một cách tiếp cận tốt hơn

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; 
    } 
}; 
+0

Đây là cách tiếp cận tôi 'd mất. Ngoại trừ tôi sẽ thay thế 'find' bằng [some] (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/some) – CodingIntrigue

+0

@CodingIntrigue cảm ơn bạn đã bổ sung. Tôi đã cập nhật câu trả lời. – bennygenel

1

Giải pháp:

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; 
    } 
}; 

Test:

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); 
Các vấn đề liên quan