score:0

Accepted answer

To update an array, I would use immutability helper and do something like this - to your reducer

 let store = {"state" : {
"data": [{
    "subset": [{
        "id": 1
    }, {
        "id": 2
    }]
}, {
    "subset": [{
        "id": 10
    }, {
        "id": 11
    }, {
        "id": 12
    }]
}]
}}

case Constants.SET_DESC:
  return update(store, {
  "state" : {
  "data": {
      [action.indexToUpdate]: {
        "subset": {
             $set: action.payload.desc
        }
      }
  }
 }
  })
  });

score:1

If you have to update an element in a array within your store you have to copy the array and clone the matching element to apply your changes.

So in the first step your action should contain either the already cloned (and changed) object or the id of the object and the properties to change.

Here is a rough example:

export class MyActions {
    static readonly UPDATE_ITEM = 'My.Action.UPDATE_ITEM';

    static updateItem(id: string, changedValues: any) {
        return { type: MyActions.UPDATE_ITEM, payload: { id, changedValues } };
    }
}

export const myReducer: Reducer<IAppState> = (state: IAppState = initialState, action: AnyAction): IAppState => {
    switch (action.type) {
        case MyActions.UPDATE_ITEM:
            return { ...state, items: merge(state.items, action.payload) };

        default:
            return state;
    }
}

const merge = (array, change) => {
    // check if an item with the id already exists
    const index = array.findIndex(item => item.id === change.id);
    // copy the source array
    array = [...array];

    if(index >= 0) {
        // clone and change the existing item
        const existingItem = array[index];
        array[index] = { ...existingItem, ...change.changedValues };
    } else {
        // add a new item to the array
        array.push = { id: change.id, ...change.changedValues };
    }

    return array;
}

score:2

The following example taken from the redux documentation might help you in the use case how to update items in an array. For more on this you can read on here http://redux.js.org/docs/recipes/StructuringReducers.html

state structure is something like this

{
  visibilityFilter: 'SHOW_ALL',
  todos: [
    {
      text: 'Consider using Redux',
      completed: true,
    },
    {
      text: 'Keep all state in a single tree',
      completed: false
    }
  ]
}

and reducer code is like below

function updateObject(oldObject, newValues) {
    // Encapsulate the idea of passing a new object as the first parameter
    // to Object.assign to ensure we correctly copy data instead of mutating
    return Object.assign({}, oldObject, newValues);
}

function updateItemInArray(array, itemId, updateItemCallback) {
    const updatedItems = array.map(item => {
        if(item.id !== itemId) {
            // Since we only want to update one item, preserve all others as they are now
            return item;
        }

        // Use the provided callback to create an updated item
        const updatedItem = updateItemCallback(item);
        return updatedItem;
    });

    return updatedItems;
}

function appReducer(state = initialState, action) {
    switch(action.type) {
        case 'EDIT_TODO' : {
            const newTodos = updateItemInArray(state.todos, action.id, todo => {
                return updateObject(todo, {text : action.text});
            });

            return updateObject(state, {todos : newTodos});
        } 
        default : return state;
    }
}

Related Query

More Query from same tag