1

I'm trying to add a single item to my nested Redux state, if that item isn't already in the list.

I don't care about doing it in plain JS, I want the Redux sauce ofc.

My state looks like this:

  state: {
    data: {
      list: []
    },
  },

This is what I tried in my reducer:

  return {
    ...state,
    data: {
      ...state.data,
      list: [action.payload.list, ...state.data.list]
    }
  }

Problem is, sometimes the item I want to add is already in the array, therefore I have a duplicate in my list (which I don't want).

How can I add an item to my list while checking first if this item is already there?

mokiliii Lo
  • 587
  • 3
  • 13
  • 26
  • Possible duplicate of [How do I check if an array includes an object in JavaScript?](https://stackoverflow.com/questions/237104/how-do-i-check-if-an-array-includes-an-object-in-javascript) – Tomasz Mularczyk Jun 02 '18 at 13:47

2 Answers2

4

You can use some method. It will return true or false and stop iterating over the array as soon as there is a match. Example:

case SOME_ACTION: {
  // iterate over the list and compare given item to item from action
  const existsInArray = state.data.list.some(l => l.id === action.payload.list.id)
  if(existsInArray) {
    return state;
  }

  return {
    ...state,
    data: {
      ...state.data,
      list: [action.payload.list, ...state.data.list]
    }
  }
}

EDIT:

You wrote in a comment that if the element exists in the array you want to make that it will be the first item in the list. What I would do is filter out this element (if exists) and then put the item back from the action as the first element:

case SOME_ACTION: {
  // filter out the element
  const copyOfArray = state.data.list.filter(l => l.id !== action.payload.list.id)
  // put to the beginning of the array
  copyOfArray.unshift(action.payload.list);

  return {
    ...state,
    data: {
      ...state.data,
      list: copyOfArray
    }
  }
}
Tomasz Mularczyk
  • 34,501
  • 19
  • 112
  • 166
1

Element won't be duplicated and always at 0 index,

return {
    ...state,
    data: {
      ...state.data,
      list: [].concat(action.payload.list, state.data.list.filter(val=>val.id==action.payload.list.id))
    }
  }
Anurag Awasthi
  • 6,115
  • 2
  • 18
  • 32