1

How can I update multiple properties in my state object with and array of objects?

I have my state in this format:

{
 1: { id: 1, values: [ 1, 2] },
 2: { id: 2, values: [ 1, 2] }
}

In my reducer I receive the data to update the state in this format:

[
 { id: 1, values: [ 3, 4] },
 { id: 2, values: [ 3, 4 ] }
]

I want to be able to add the values from the objects coming into the reducer to matching object values in the state.

I would like to end up with:

{
 1: { id: 1, values: [ 1, 2, 3, 4] },
 2: { id: 2, values: [ 1, 2, 3, 4] }
}

I tried to map through this but then it was returning my state into an array. I want to keep my state as an object.

2 Answers 2

4

The map solution was almost correct! I would recommend doing forEach instead and don't return anything, but rather access a copy of state by id and modify those values (make sure you deep clone your state to avoid mutation). Then return the new state:

const myReducer = (state, action) => {
  const newState = someDeepCloneFunction(state);
  action.forEach(obj => {
    newState[obj.id] = obj.values
  })
  return newState
}
Sign up to request clarification or add additional context in comments.

1 Comment

action.payload.forEach?
3

Transform the data before it reaches your reducer, whether that's in an action, thunk, saga, or component.

const transform = (data = []) => {
    const mappedData = {};
    data.forEach(item => mappedData[item.id] = item);
    return mappedData
}

// ...
data = transform(data)

This keeps reducer logic cleaner

const myReducer = (state = {}, { type, data = {}, id, values = [] }) => {
    case 'SET_ALL':
        return data;
    case 'SET_MULTIPLE':
        return {
            ...state,
            ...data
        };
    case 'SET':
        return {
            ...state,
            [id]: values
        };
    case 'APPEND_VALUES':
        return {
            ...state,
            [id]: { 
                ...state[id], 
                values: [...state[id].values, ...values] 
            }
        }
    default:
        return state;
}

8 Comments

Once you have transformed the data, are you sending all of the objects at once or one at a time to the reducer?
In this example you could send all at once in a 'SET_ALL' or 'SET_MULTIPLE' action, or you could set one at a time in a 'SET' action
The part that I'm struggling with is in the 'SET_MULTIPLE', I want to concat the values array from the state with the values array in data, if I spread both state and data, I will only get the new data values.
spreading state and data will concat any new values and overwrite any existing ones
added a handler to append on a single item. Multiple might be tricky, but I'm sure you could figure that out if you get the gist of this code
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.