2017-05-06 8 views
0

我需要更新我的狀態片段而不更新整個片段;只有子片。我見過其他人結合減速機來完成這一點,但我還沒有想出如何在我的項目中做到這一點。 Redux.js.org表明這是另一種方式來做到這一點:如何在沒有擴展運算符的情況下更改Redux狀態的子片段

function updateVeryNestedField(state, action) { 
    return { 
     ....state, 
     first : { 
      ...state.first, 
      second : { 
       ...state.first.second, 
       [action.someId] : { 
        ...state.first.second[action.someId], 
        fourth : action.someValue 
       } 
      } 
     } 
    } 
} 

不幸的是,我的項目是在JavaScript。我怎樣才能複製這與香草JavaScript沒有傳播運算符?我嘗試了一些使用Object.assign的變體,但無法使其正常工作。

回答

1

正如你提到的,你可以在地方蔓延的使用Object.assign

{...state, x: 1} 

應該給你同樣的結果

Object.assign({}, state, {x: 1}) 

注意空對象爲Object.assign第一個參數。這樣做是將state中的值複製到一個新的空對象中,然後將{first: 1}中的值複製到新對象中。

例如:

var a = { x: 1, y: 2} 
var b = {...a, y: 3 } 
console.log(a); // { x: 1, y: 2 } 
console.log(b); // { x: 1, y: 3 } 

相當於

var c = { x: 1, y: 2 } 
var d = Object.assign({}, a, { y: 3 }); 
console.log(c); // { x: 1, y: 2 } 
console.log(d); // { x: 1, y: 3 } 

最重要的部分是,無論ac不變。 bd對於y具有新值。

對於嵌套對象,重複這個過程:

function updateVeryNestedField(state, action) { 
    return Object.assign({}, state, { 
     first : Object.assign({}, state.first, { 
      second : Object.assign({}, state.first.second, { 
       [action.someId] : Object.assign({}, 
        state.first.second[action.someId], 
        { fourth : action.someValue } 
       ) 
      }) 
     }) 
    }); 
} 

var oldState = { first: { second: { 'anId': { fourth: 3 } } } }; 
var newState = updateVeryNestedField(oldState, { someId: 'anId', someValue: 5 }); 
console.log(oldState.first.second.anId.fourth); // 3 
console.log(newState.first.second.anId.fourth); // 5 

然而,對於全ES2015支持,你也將無法use computed keys。所以相反,你應該在return語句之前構建一些對象。例如:

function updateVeryNestedField(state, action) { 
    // Create a temporary object to avoid use of computed keys 
    var updatedSecond = Object.assign({}, state.first.second); 
    updatedSecond[action.someId] = Object.assign({}, state.first.second[action.someId], { 
     fourth: action.someValue 
    }); 
    return Object.assign({}, state, { 
     first : Object.assign({}, state.first, { second : updatedSecond }) 
    }); 
} 

var oldState = { first: { second: { 'anId': { fourth: 3 } } } }; 
var newState = updateVeryNestedField(oldState, { someId: 'anId', someValue: 5 }); 
console.log(oldState.first.second.anId.fourth); // 3 
console.log(newState.first.second.anId.fourth); // 5 
+0

簡單完美 - 謝謝。 – skwny

+0

這在es5中是否允許:'[action.someId]:...'?使用uglifier.js進行縮小時會引發錯誤,而其他人也會遇到此問題。然而,它在捆綁但不縮小時通過。 – skwny

+0

@skwy不幸的計算鍵是ES2015的一部分。我已更新我的示例以說明如何通過引入臨時對象來避免使用計算密鑰。新示例使用索引將屬性添加到臨時對象。 – grovesNL

相關問題