20

I stuck with this bit and I can't progress - I guess solution is simple but I can't figure out. I'm trying to add entry in reducer so data in in would look something this:

state = {
  entryId: {
    entryName: ["something", "something2", "something3" /* and so on... */]
  }
};

So far this is the closest I get, but, instead of adding new unique entry, it is replacing the one that is stored already. Also I need to be able to add this item to empty state where entryId, entryName doesn't exist yet to avoid error:

switch(type) {
  case ADD_ENTRY:
    return {
      ...state,
      [entryId]: {
        ...state[entryId],
        [entryName]: {
          [uniqueEntry]: true
        }
      }
    };
}

Any idea what I'm doing wrong?

eloleon
  • 1,144
  • 2
  • 10
  • 18
  • Can you write a more context to the example? For example, can you indicate the _shape_ of the action you are handling intros reducer? – Eloy Pineda Jun 20 '16 at 22:36
  • I'm dispatching something like this: addEntry({ entryId, entryName, uniqueEntryid }) – eloleon Jun 20 '16 at 22:38
  • Try this: [link](https://babeljs.io/repl/#?evaluate=true&lineWrap=false&presets=es2015%2Creact%2Cstage-2%2Cstage-3&code=const%20state%20%3D%20%7B%0D%0A%20%20entryId%3A%20%7B%0D%0A%20%20%20%20entryName%3A%20%5B%22something%22%2C%20%22something2%22%2C%20%22something3%22%5D%0D%0A%20%20%7D%0D%0A%7D%3B%0D%0A%0D%0Aconst%20newState%20%3D%20%7B%0D%0A%20%20%5B%22entryId%22%5D%3A%7B%0D%0A%20%20%20%20%5B%22entryName%22%5D%3A%20%5B...state%5B%22entryId%22%5D%5B%22entryName%22%5D%2C%22something4%22%5D%0D%0A%20%20%7D%0D%0A%7D%3B%0D%0A%0D%0Aconsole.log(newState)%3B&experimental=true&loose=false&spec=false) – mnsr Jun 20 '16 at 23:03
  • thanks jzm for an effort. I've tried something similar but the issue is with initial state / first entry, entryId is undefined. You can see the issue I'm having when you set initial state to empty object i.e. const state = {}; And since all values are dynamic, I can't have different initial state – eloleon Jun 21 '16 at 07:41

1 Answers1

23

If you're trying to add an element to the end of the entryName array you should be doing:

return {
  ...state,
  [entryId]: {
    ...state[entryId],
    [entryName]: [
      ...state[entryId][entryName],
      uniqueEntry
    ]
  }
};

ES6 spread with arrays works like this:

const array1 = [1, 2, 3];
const array2 = [4, 5, 6];
const eight = 8;

const newArray = ['stuff', ...array1, 'things', ...array2, ...[7, eight], 9];
console.log(newArray); // ["stuff", 1, 2, 3, "things", 4, 5, 6, 7, 8, 9]

Check out this gist which has an example of something very similar to what you're doing.

I found this set of examples extremely helpful as well. A lot of great stuff in here:

https://github.com/sebmarkbage/ecmascript-rest-spread

Update:

If entryName is initialized to undefined like you say in your comment, you could do this:

return {
  ...state,
  [entryId]: {
    ...state[entryId],
    [entryName]: [
      ...state[entryId][entryName] || [],
      uniqueEntry
    ]
  }
};

I think this is a pretty great example of how painful it can be working with React/redux using a heavily nested data structure. FWIW, it's been recommended to me many times to flatten your state as much as possible.

jaybee
  • 2,240
  • 14
  • 20