2016-09-22 93 views
2

我的狀態在我的redux存儲區中是Immutable.js類型,我只能在我的還原器中更改狀態。跳過使用不可變並且有一個解析器根據命令檢查我的應用並警告我是否將商店更改爲reducer功能之外沒有更多意義嗎?或者是否有充分的理由說明爲什麼沒有這樣做?爲什麼需要不可變狀態的redux

+0

如果你不想依賴immutable.js,你可以使用[deep-freeze](https://www.npmjs.com/package/deep-freeze)和[Object.assign()](https:// developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Object/assign)。問題是更新凍結對象變得單調乏味,特別是對於嵌套對象,例如Object.assign({},freezedObj,{a:1,b:Object.assign({},freezedObj.b,{c:2})。 });你可以查看[ImmutableAssign](https://github.com/engineforce/ImmutableAssign),這是一個輕量級的不可變幫助器,可以簡單地在賦值之上。 – engineforce

回答

3

如果您喜歡,您可以在減速器中改變您的狀態。 Redux並沒有要求你不要改變你的狀態,但建議不要這樣做。

React-Redux不是Redux,它的設計假定狀態永遠不會發生變異。這使得它可以快速檢查以查明狀態層次結構中是否有任何改變。

Redux本身會在每次處理操作時觸發事件,無論它是否修改(通過變異或替換)狀態。它從不檢查除undefined之外的狀態。它不關心你用它做什麼。

不可變狀態有許多好處,但在Redux中使用的主要好處是檢查修改是快速的。舉例來說,你的「解析器」需要訪問每個對象和數組中每個對象和數組的每一個屬性和項目,每次運行它時都會做出有意義的決定。如果React-Redux做了同樣的事情,那麼它會非常緩慢,沒有人會使用它。因此,成千上萬的開發者正在限制自己的不變性,因爲它具有超越學術界的真正優勢。

1

有幾個方面對這個問題:

  • 終極版鼓勵你寫純函數爲你減速。這使得時間旅行調試等功能變得更加可測試。 「純」意味着沒有任何副作用,這意味着你不應該直接修改任何通過的數據。相反,數據更新應該是不可變的(即通過複製你想要更新的數據部分)
  • React - Redux的connect函數假定更新將不可改變地完成,並進行參考比較以查看傳入數據是否已更改。如果對象引用與以前相同,則它假定沒有任何更改,並且不會導致組件重新呈現。

但是請注意,「不可改變的更新」不意味着你必須使用Immutable.js庫。完全可以以不可變的方式更新純JS對象。

作爲我的React/Redux links list的一部分,我有許多有關這些主題的有用文章的鏈接。尤其請參閱Immutable Data ManagementFunctional Programming的類別。我還有另外一個頁面列出了各種immutable data-related libraries,包括可以更容易更新純JS數據的實用程序。最後,我列出了一些Redux-related dev tools的列表,其中包括一些工具,它們會在您意外改變您的狀態時提醒您。

2

我認爲您的某種中間件可以檢查無意狀態突變的想法實際上是一個非常酷的想法。我不確定它的可行性/性能如何(它甚至可能已經存在,我只是沒聽說過)。但是,對於那些不使用Immutable.js或seamless-immutable等類型庫的人,我可以看到這將會有用。

我只是想澄清,不可變。js強制你不改變你的狀態,這只是一個結果,它不可能從你的reducer之外改變你的狀態。不變性的一般編程概念與僅使用reducer來改變狀態的Redux特有概念之間存在着重要的區別。 Immutable.js強制執行前者,從邏輯上強制執行後者。

但是,Immutable.js確保您不會意外地發生變異狀態的事實是不使用庫,供您終極版店的唯一理由:

  • 性能:Immutable.js具有性能優化它允許它在實際共享內存中相同的底層對象時強制不變性。這意味着,例如,您不是爲了更改數組中的單個項目而執行大量數據的深層副本。這可能意味着在商店有大量數據和/或狀態發生很多變化的情況下,內存佔用量會大大減少。
  • 幫助程序方法:雖然你可以使用各種技術來避免變異狀態,Immutable.js有一個非常好的API來做到這一點。例如,如果你曾經嘗試過改變那些深深嵌套在數組和對象中的東西,你會注意到它非常難以用原生JS實現。 Immutable.js可以很容易地深入挖掘並更改某些內容,並將它們連接在一起。

    return state 
     .updateIn(['todos', '5', 'attachment'], attachment => attachment.set('name', 'foo')) 
     .set('isProcessing', true) 
     .updateIn(['other', 'nested', 'stuff'], stuff => stuff.set('bar', 'baz')); 

話雖這麼說,這絕對是可選的。你有一個像上述無縫,不可變的,lodash-FP的替代品,而只是做手工,像這樣:

return Object.assign({}, state, { name: 'new name' }); 

相比之下,Immutable.js替代也只是:

return state.set('name', 'new name');