简体   繁体   中英

Updating an object within array in react redux reducer getting map() is not a function

I have a fairly complex/nested redux store like this:

{
  object1
  {
    array:
    [
      object[1]: {
        id: 1,
        replace: ""
      }
      object[2]: {
        id: 2
        replace: ""
      }
      object[3]: {
        id: 3,
        replace: ""
      }
    ]
  }
}

After dispatching an action, I need to insert the action to one of the object[] based on ID. I am currently using the following scripts to update replace within the reducer. However this will change the array to an object due to the curly bracket of object2: {} .

case UPDATE:
  return {
    ...state,
    object1: {
      ...state.object1,
      array: {
        ...state.object1.array,
        [action.id]: {
          ...state.object1.array[action.id],
          replace: action.result
        }
      }
    }
  };

My render will breaks after that since object2.map is no longer a function after changing to object. How do I workaround this without converting it to an object?

The following will failed with syntax error:

case UPDATE:
  return {
    ...state,
    object1: {
      ...state.object1,
      array: [
        ...state.object1.array,
        [action.id]: {
          ...state.object1.array[action.id],
          replace: action.result
        }
      ]
    }
  };

You cannot directly specify the index that you want to modify with spread syntax, you need to first find the index and do it like

case UPDATE:
  var idx = state.object1.object2.findIndex(obj => obj.id === action.id)
  return {
    ...state,
    object1: {
      ...state.object1,
      object2: [
        ...state.object1.object2.slice(0, idx),
        {
            ...state.object1.object2[idx],
            replace: action.result 
        }
        ...state.object1.object2.slice(idx + 1)
      ]
    }
  };

Or else you can make use of immutability-helper package. See this answer for a sample of how to do it

how to use Immutability helper to update a nested object within an array?

'You can check the library immutadot . Its purpose is to help update complex nested data structure in a very concise way and was created with redux usage in mind.

In your case you can write it this way :

import { set } from 'immutadot'

...

  case UPDATE:
    return set(state, 'object1.arrary[' + id + '].replace', action.result)
    // or with templated string
    return set(state, `object1.arrary[${ id }].replace`, action.result)

...

It relies on lodash under the wood so you can use all faculties of lodash's functions.

Following code for using immutability-helper package.

case UPDATE:
  return update(state, {
    object1: {
      array: {
        [action.id]: {
          replace: {
            $set: action.result
          },
        },
      },
    }
  });

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM