背景是 React + mobx@4.x + antd 的項目,而且打開了嚴格模式的狀況下:es6
configure({ enforceActions: true })
大概個人需求是, 將store 中的一個數組(dataSource)在stateless Component中進行渲染,那麼天然就想到了Array 的 map 方法,而後再JSX中直接將數組轉成JSX 代碼塊。數組
const wrapperItem = (title, list) => { const result = list.map((item, index) => <Row> <Col span={2}> {index} </Col> <Col span={2}> {item} </Col> </Row>) return ( <div> <h4>{title}</h4> {result} </div> ) }
上面的demo 代碼中的第二個參數list 會傳入observable 屬性----是一個數組。promise
而後瀏覽器狂報錯誤:瀏覽器
[mobx] Since strict-mode is enabled, changing observed observable values outside actions is not allowed. Please wrap the code in an `action` if this change is intended. Tried to modify: SupernatantStore@13.data.baseInfo
而後看一下 下面的簡單代碼排查錯誤吧:antd
var list = [{'a': 1},{'a': 2}]; var newList = list.map(function(index){ return index.a += 1; }); console.log(newList,'newList',list,'list'); // newList 和 list 都改變了。先修改了list的單個key值,再將key值返回,天然就修改了兩個 var list = [{'a': 1},{'a': 2}]; var newList = list.slice(0).map(function(index){ return index.a += 1; }); console.log(newList,'newList',list,'list'); // newList 和 list 也都改變了,關鍵很不理解,明明 list 跟 list.slice(0) 已經不是指向同一個數組,爲何list.slice(0) 修改內容還會引起list 也改變? // wa ... // 難受的一批。。。 // slice() concat() 都是淺拷貝,整個數組的指向是不一樣的了,可是,裏面的對象的指向是同一個,因此其實在map裏執行的函數,操做的對象仍是同一個。。。 list.slice(0)[0] === list[0] // truw list.slice(0) === list // false
一樣的,es6 的解構賦值,也只是淺拷貝:app
var a = {b: {c:111},d:{d:2222}} var {b} = a b === a.b // true
因此說,mobx嚴格模式下一直再警告我不能修改observable 的值。less
constructor() { this.initData() } @action initData = async () => { this.baseInfo = await getBaseInfo() this.extractInfo = await getExtractInfo() this.extractInfo = await getExtractStatus() }
我以前的代碼是這樣的,其實,我以爲連@action
也不要,由於就算在嚴格模式下constructor
函數中也是能夠修改observable中的值的。異步
那爲何一直報不能在action
以外修改observable 屬性的錯誤呢? async
action 僅影響當前運行的函數,而不會影響異步函數,這意味着若是你有setTimeout,promise, then 或 異步的constructor ,在回調更多的狀態改變,這些回調應包裝在 runInAction 中。。。。ide
寫在最後:
set
的時候,我每每只關心我獲得的值(return 出來的)是否是我想要的。。。。slice
,concat()
產生一個新的數組這一個概念的理解,只停留於表面。。。。