Oleksandr Fomin
Oleksandr Fomin

Reputation: 2376

Update nested object's property in Redux

My Redux state has the following structure:

const state = {
 transactions: {
    1: {
       TransactionId: 1, Status: "Pending", Type: "Withdrawal", ClientName: "Paul Carter", Amount: "$28.43"
    },

    2: {
      TransactionId: 2, Status: "Completed", Type: "Refill", ClientName: "Caldwell Reid", Amount: "$45.16"
  },
...
}

What is the correct way to update/delete an object from transactions given that I have an id ?

Here is how I tried to update Status property in my reducer but it didn't seem to work, my state remains unchanged.

const transactionsReducer = (state, action) => {
    case CHANGE_TRANSACTION_STATUS:
      return {
        [state.transactions[action.id].Status]: action.status
       }
}

Upvotes: 0

Views: 36

Answers (3)

cucaracho
cucaracho

Reputation: 184

transactions should be an array (it's a collection of entities). The 'id' key is redundant, it's already represented by 'TransactionId' (single source of truth). like this:

const state = {
 transactions: [
     {
       TransactionId: 1, Status: "Pending", Type: "Withdrawal", ClientName: "Paul Carter", Amount: "$28.43"
    },

     {
      TransactionId: 2, Status: "Completed", Type: "Refill", ClientName: "Caldwell Reid", Amount: "$45.16"
  },
...
]

then you can simply use filter for delete and map for update:

return {
    ...state,
    transactions: state.transactions.filter(txn => txn.TransactionId !== action.deletedId)
}

Upvotes: 0

Ajeet Shah
Ajeet Shah

Reputation: 19863

You can do this:

const transactionsReducer = (state, action) => {
  switch (action.type) {
    case CHANGE_TRANSACTION_STATUS:
      return {
        ...state,
        transactions: {
          ...state.transactions,
          [action.id]: {
            ...state.transactions[action.id],
            Status: action.status
          }
        }
      }
  }
}

Also, I personally think, it is better to use small-casing here for property names to avoid mistakes. Example:

transactionId: 1, status: "Pending", type: "Withdrawal", clientName...

Upvotes: 2

Vivek Doshi
Vivek Doshi

Reputation: 58613

Here you go, it should look something like this :

if you are getting transactions object within state directly :

return {
    ...state,
    [action.id]: {
        ...state[action.id] ,
        Status : action.status
    }
}

And if not then, you need to use this :

return {
    ...state,
    transactions : {
        ...state.transactions ,
        [action.id]: {
            ...state.transactions[action.id] ,
            Status : action.status
        }
    }
}

Upvotes: 1

Related Questions