tonilaukka
tonilaukka

Reputation: 65

Immutable.js update deeply nested Map

I'm having trouble updating a redux store. I have tabular data in store and the update patch comes in with selection and the value to be updated. The state of the store looks like this:

const state = fromJS({
  data: {
    rows: {
      row1: {
        col1: { amount: 1 },
        col2: { amount: 1 },
        col3: { amount: 1 },
        col4: { amount: 1 },
      },
      row2: {
        col1: { amount: 2 },
        col2: { amount: 2 },
        col3: { amount: 2 },
        col4: { amount: 2 },
      },
      row3: {
        col1: { amount: 3 },
        col2: { amount: 3 },
        col3: { amount: 3 },
        col4: { amount: 3 },
      },
      row4: {
        col1: { amount: 4 },
        col2: { amount: 4 },
        col3: { amount: 4 },
        col4: { amount: 4 },
      },
    }
  }
});

const newAmount = 5;

const selection = [
  { row: 'row1', column: 'col1' },
  { row: 'row1', column: 'col2' },
  { row: 'row2', column: 'col1' },
  { row: 'row2', column: 'col2' },
];

Selection can be only one cell or multiple cells on one or more rows. Each cell should be updated with the same value. What is the proper way to update the store so that the next state would look like this.

const nextState = fromJS({
  data: {
    rows: {
      row1: {
        col1: { amount: 5 }, // updated with newAmount 
        col2: { amount: 5 }, // updated with newAmount
        col3: { amount: 1 },
        col4: { amount: 1 },
      },
      row2: {
        col1: { amount: 5 }, // updated with newAmount
        col2: { amount: 5 }, // updated with newAmount
        col3: { amount: 2 },
        col4: { amount: 2 },
      },
      row3: {
        col1: { amount: 3 },
        col2: { amount: 3 },
        col3: { amount: 3 },
        col4: { amount: 3 },
      },
      row4: {
        col1: { amount: 4 },
        col2: { amount: 4 },
        col3: { amount: 4 },
        col4: { amount: 4 },
      },
    }
  }
});

Upvotes: 0

Views: 400

Answers (1)

enapupe
enapupe

Reputation: 17059

The easiest way (code-wise) I could find is:

const newState = state.withMutations(newStore => {
  selection.forEach((selection) => {
    newStore.setIn(['data', 'rows', selection.row, selection.column, 'amount'], newAmount)
  }) 
})

The benefit of this approach is that you just iterate what is going to change. I don't think it's worth to do it without withMutation because the code may look quite hard to deal with.

Upvotes: 1

Related Questions