在不改变状态的情况下用另一个替换数组项

IT技术 reactjs state redux mutation
2021-05-10 09:09:08

这是我的状态示例的外观:

const INITIAL_STATE = {
 contents: [ {}, {}, {}, etc.. ],
 meta: {}
}

我需要能够并以某种方式替换知道其索引的内容数组中的项目,我尝试过:

      return {
        ...state,
        contents: [
          ...state.contents[action.meta.index],
          {
            content_type: 7,
            content_body: {
              album_artwork_url: action.payload.data.album.images[1].url,
              preview_url: action.payload.data.preview_url,
              title: action.payload.data.name,
              subtitle: action.payload.data.artists[0].name,
              spotify_link: action.payload.data.external_urls.spotify
            }
          }
        ]
      }

action.meta.index我想用另一个内容对象替换的数组项的索引在哪里,但我相信这只是将整个数组替换为我正在传递的这个对象。我也想过使用,.splice()但这只会改变数组?

3个回答

需要注意的是Array.prototype.map()文档)并没有发生变异原数组所以它提供了另一种选择:

 const INITIAL_STATE = {
   contents: [ {}, {}, {}, etc.. ],
   meta: {}
 }

 // Assuming this action object design
 {
   type: MY_ACTION,
   data: {
     // new content to replace
   },
   meta: {
     index: /* the array index in state */,
   }
 }

 function myReducer(state = INITIAL_STATE, action) {
   switch (action.type) {
     case MY_ACTION: 
       return {
         ...state,
         // optional 2nd arg in callback is the array index
         contents: state.contents.map((content, index) => {
           if (index === action.meta.index) {
             return action.data
           }

           return content
         })
       }
   }
 }

只是为了建立在@sapy 的正确答案上。我想向您展示如何在 Redux 中更改数组内对象的属性而不改变状态的另一个示例。

我的状态中有一个数组orders每个order都是一个包含许多属性和值的对象。但是,我只想更改note属性。所以像这样的事情

let orders = [order1_Obj, order2_obj, order3_obj, order4_obj];

例如在哪里 order3_obj = {note: '', total: 50.50, items: 4, deliverDate: '07/26/2016'};

所以在我的 Reducer 中,我有以下代码:

return Object.assign({}, state,
{
  orders: 
    state.orders.slice(0, action.index)
    .concat([{
      ...state.orders[action.index],
      notes: action.notes 
    }])
    .concat(state.orders.slice(action.index + 1))
   })

因此,基本上,您正在执行以下操作:

1) 在order3_objso之前切出数组[order1_Obj, order2_obj]

2)order3_obj通过使用三点...扩展运算符和您要更改的特定属性(即note)连接(即添加)编辑

3) 在订单数组的其余部分使用.concat.slice最后连接.concat(state.orders.slice(action.index + 1)),这是之后的所有内容order3_obj(在这种情况下order4_obj是唯一剩下的)。

Splice改变你需要使用的数组Slice而且你还需要concat切片。

return Object.assign({}, state,  {
         contents:
          state.contents.slice(0,action.meta.index)
          .concat([{
            content_type: 7,
            content_body: {
              album_artwork_url: action.payload.data.album.images[1].url,
              preview_url: action.payload.data.preview_url,
              title: action.payload.data.name,
              subtitle: action.payload.data.artists[0].name,
              spotify_link: action.payload.data.external_urls.spotify
            }
          }])
          .concat(state.contents.slice(action.meta.index + 1))
  }