2016-02-12 45 views
9

ten sposób przykładem mojego stanu wygląda:Wymienić element tablicy z innym bez mutacji stan

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

muszę być w stanie i jakoś zastąpić element wewnątrz treści tablicy znając jego indeks, próbowałem:

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

gdzie action.meta.index jest indeks elementu tablicy Chcę zastąpić innym zawartości obiektu, ale wierzę, że to po prostu zastępuje całą tablicę do tego jednego obiektu olewam. Myślałem również o użyciu .splice(), ale to tylko zmutować tablicy?

+1

również przyjrzeć się reagować na pomocników niezmienność - https://facebook.github.io/ react/docs/update.html Nie są tak trudne w użyciu, jak wyglądają i naprawdę ułatwiają odczytanie kodu. – Andreyco

Odpowiedz

4

Splice zmutować macierz, której potrzebujesz użyć Slice. Musisz również concat pokrojony kawałek.

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

Edytowano. Domyślam się, że próbujesz wysłać cały stan z wartością treści zmienioną. Tak więc, użyj Object.assign, aby wysłać nowy stan, i jeśli istnieje wiele źródeł dla tego samego klucza w Object.assign, ostatnie źródło wygrywa. – sapy

8

Tylko po to, aby zbudować odpowiedź @ sapy, która jest właściwa. Chciałem pokazać inny przykład, jak zmienić właściwość obiektu wewnątrz tablicy w Redux bez mutowania stanu.

Posiadałem tablicę orders w moim stanie. Każdy obiekt order jest obiektem zawierającym wiele właściwości i wartości. Ja jednak chciałem tylko zmienić właściwość note. Więc niektóre rzeczy jak ten

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

gdzie na przykład order3_obj = {note: '', total: 50.50, items: 4, deliverDate: '07/26/2016'};

więc w moim reduktor, miałem następujący kod:

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

tak zasadniczo, robisz co następuje:

1) Pokrój tablicę przed order3_obj, aby [order1_Obj, order2_obj]

2) Concat (czyli dodać) edytowany order3_obj stosując trzy kropki ... operatora rozprowadza i szczególną właściwość, którą chcesz zmienić (np note)

3) Concat w pozostałej części tablicy zamówień za pomocą .concat i .slice na końcu .concat(state.orders.slice(action.index + 1)), co jest wszystkim po order3_obj (w tym przypadku tylko jeden order4_obj).

+2

Dziękuję bardzo! Super pomocne wyjaśnienie – Alastair

+0

to mi bardzo pomogło. dla tego – user1189352

5

Zauważ, że Array.prototype.map() (docs) robi nie mutować oryginalną tablicę dlatego stanowi kolejną opcję:

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

Zdecydowanie najbardziej eleganckie rozwiązanie. –