2016-02-12 9 views
9

परिवर्तनशील बिना एक दूसरे के साथ सरणी आइटम की जगह यह कैसे मेरे राज्य के उदाहरण दिखाई देता है:राज्य

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() का उपयोग करने के बारे में भी सोचा था, लेकिन यह सिर्फ सरणी को बदल देगा?

+1

इसके अलावा, प्रतिक्रिया के अचल स्थिति सहायकों पर एक नज़र डालें - https://facebook.github.io/ प्रतिक्रिया/दस्तावेज़/update.html वे उपयोग करने के लिए उतना कठिन नहीं हैं जितना वे दिखते हैं और वास्तव में आपके कोड को पढ़ने में आसान बनाते हैं। – Andreyco

उत्तर

4

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

संपादित किया गया। मुझे लगता है कि आप सामग्री मूल्य बदलकर पूरे राज्य को भेजने की कोशिश कर रहे हैं। तो, नया राज्य भेजने के लिए ऑब्जेक्ट.साइन का उपयोग करें, और यदि ऑब्जेक्ट.साइन में एक ही कुंजी के लिए कई स्रोत हैं, तो अंतिम स्रोत जीतता है। – sapy

8

बस @ सैपी के उत्तर पर निर्माण करने के लिए जो सही है। मैं आपको एक और उदाहरण दिखाना चाहता था कि राज्य को म्यूट किए बिना रेडक्स में किसी सरणी के अंदर किसी वस्तु की संपत्ति को कैसे बदला जाए।

मेरे पास मेरे राज्य में 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'};

मेरी प्रसारण में

तो के लिए, मैं निम्नलिखित कोड था:

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) Concat (यानी में जोड़ें) तीन डॉट ... प्रसार ऑपरेटर और विशेष रूप से संपत्ति आप .concat का उपयोग करके आदेशों सरणी के बाकी हिस्सों में (यानी note)

3) Concat बदलना चाहते हैं का उपयोग करके संपादित order3_obj और .slice अंत में .concat(state.orders.slice(action.index + 1)) जो order3_obj के बाद सब कुछ है (इस मामले में order4_obj केवल एक ही छोड़ दिया गया है)।

+2

आपको बहुत बहुत धन्यवाद! सुपर सहायक स्पष्टीकरण – Alastair

+0

इससे मुझे बहुत मदद मिली। इस – 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

के लिए निश्चित रूप से सबसे सुरुचिपूर्ण समाधान। –

संबंधित मुद्दे