背景是 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()
产生一个新的数组这一个概念的理解,只停留于表面。。。。