2016-02-12 12 views
9

を変異させずに、別の1と配列項目を交換してください。この私の状態の例がどのように見えるかされていますは状態

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

は、私ができることと何とかそのインデックスを知っているコンテンツ配列内のアイテムを交換する必要があり、私が試してみました:

action.meta.indexは、配列項目の指標である、私は別の内容で置き換えたい
 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 
      } 
      } 
     ] 
     } 

は、オブジェクトが、私は、これはちょうど私が渡しているこの一つのオブジェクトの配列全体を置き換えると信じています。私も.splice()を使用すると思ったが、それは配列を突然変異させるだろうか?

+1

を、のリアクト不変性ヘルパーを見てみましょう - https://facebook.github.io/反応する/ docs/update.html 彼らは見た目と同じくらい使いにくくなく、実際にコードを読みやすくしています。 – Andreyco

答えて

4

SpliceSliceを使用する必要があります。また、スライスされた部分は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)) 
    } 
+0

編集済み。コンテンツの値が変更された状態全体を送信しようとしているようです。したがって、Object.assignを使用して新しい状態を送信し、Object.assignに同じキーのソースが複数ある場合は、最後のソースが勝ちます。 – sapy

8

正しい@ @ sapyの回答を作成するだけです。状態を変更することなく、Reduxの配列内のオブジェクトのプロパティを変更する方法の別の例を示したいと思います。

私の状態はordersでした。各orderは多くのプロパティと値を含むオブジェクトです。しかし、私はnoteプロパティを変更したいだけでした。だから、order3_obj = {note: '', total: 50.50, items: 4, deliverDate: '07/26/2016'};

例えばは、だから私の減速で、私は次のコードを持っていたこの

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

のようないくつかのこと:だから、基本的に

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_objの前に配列を切り取ります。[order1_Obj, order2_obj]

2)の連結方式(すなわち3つのドット...広がりオペレータとあなたが.concatを使用して受注配列の残りの部分(すなわちnote

3)の連結方式を変更したい特定のプロパティを使用してorder3_obj編集した)で追加し、 .slice最後の.concat(state.orders.slice(action.index + 1))はすべてorder3_obj(この場合はorder4_objが残っています)の後のものです。

+2

ありがとう!非常に役立つ説明 – Alastair

+0

これは私をとても助けました。このためのty – user1189352

5

注それは別のオプションを提供して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

最も洗練されたソリューションです。 –