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

Ilj*_*lja 15 state mutation reactjs redux

这是我的州的例子:

const INITIAL_STATE = {
 contents: [ {}, {}, {}, etc.. ],
 meta: {}
}
Run Code Online (Sandbox Code Playgroud)

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

      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
            }
          }
        ]
      }
Run Code Online (Sandbox Code Playgroud)

这里action.meta.index就是我想与其他内容对象来代替数组元素的索引,但我相信这只是代替整个数组这一个对象,我路过.我也想过使用.splice()但是这会改变数组吗?

Sia*_*Sia 17

需要注意的是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
         })
       }
   }
 }
Run Code Online (Sandbox Code Playgroud)

  • 绝对是最优雅的解决方案. (3认同)

Hus*_*enK 12

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

我有一个orders在我的州的阵列.每个order都是包含许多属性和值的对象.然而,我只想改变note财产.所以这样的事情

let orders = [order1_Obj, order2_obj, order3_obj, order4_obj];
Run Code Online (Sandbox Code Playgroud)

例如 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))
   })
Run Code Online (Sandbox Code Playgroud)

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

1)前片Out阵列order3_obj,以便[order1_Obj, order2_obj]

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

3)Concat在其余的orders数组中使用.concat.slice结束.concat(state.orders.slice(action.index + 1))后的所有内容order3_obj(在这种情况下order4_obj只剩下一个).

  • 非常感谢!超级有用的解释 (2认同)

sap*_*apy 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))
  }
Run Code Online (Sandbox Code Playgroud)