将数组项替换为另一个而不改变状态

时间:2016-02-12 12:16:27

标签: reactjs state redux mutation

这是我的州的例子:

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 个答案:

答案 0 :(得分:15)

请注意,Array.prototype.map()docs会改变原始数组,因此它提供了另一种选择:

 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
         })
       }
   }
 }

答案 1 :(得分:12)

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

我的州里有一个source.filter() .do() .subscribe() 数组。每个orders都是一个包含许多属性和值的对象。但是,我只想更改order属性。所以像这样的事情

note

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

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

order3_obj = {note: '', total: 50.50, items: 4, deliverDate: '07/26/2016'};

基本上,你正在做以下事情:

1)在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)) }) order3_obj

之前切出数组

2)使用三点[order1_Obj, order2_obj]点差运算符和您想要更改的特定属性(即order3_obj

,对已编辑的...进行Concat(即加入)

3)使用note.concat结尾.slice的其余订单数组中的Concat,这是.concat(state.orders.slice(action.index + 1))之后的所有内容(在这种情况下为order3_obj是剩下的唯一一个。)

答案 2 :(得分:5)

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))
  }