ckinmind/ReactCollect

关于mobx中的action(写法问题,必须包裹在匿名函数里(并非必须,写成箭头函数的形式))

ckinmind opened this issue · 4 comments

在测试一个简单的Counter时遇到的问题

class CounterStore {
    @observable count=0;

    @action increment(){
        this.count ++;
    }
    @action decrement(){
        this.count --;
    }
}

@observer
class Counter extends React.Component{

 render(){
        return (
               ...
              <span onClick={this.todoStore.decrement} className={cx('span','l')}>-</span>
                 {this.todoStore.count}
             <span onClick={()=>this.todoStore.increment()} className={cx('span', 'r')}>+</span>
                   ...
        )}

这里的两种写法,一种是this.todoStore.decrement另一种是()=>this.todoStore.increment()
结果第二种不起作用, 为什么

关于mobx中action的作用

  • 任何修改state的操作都称为actions。action接收一个函数,并用untracked,untracked和allowStateChanges包裹后再返回

进一步测试发现:(此处的描述不太准确,看下面的描述)

  • 如果store中使用@action申明的方法在,在组建中调用的时候必须包裹在匿名函数里
  • 如果没有使用@action但是方法用涉及到store中的状态改变,会报错
  • 没有使用@action可以正常的调用无须包裹在匿名函数里
import {observable, action} from 'mobx'
import NattyFetch from 'natty-fetch'

export default class DemoStore {
    // 被观察的属性
    @observable content = ''

    // 同步action示例
    @action clearContent() {
        this.content = ''
    }

    test(){
        console.log('123');
        //this.content = 'test again';
    }
}

....
//组件中
const stroeTest = new DemoStore();
...
<div>
      <div>test测试:</div>
              <Button onClick={stroeTest.test}>test</Button>
              <div>{stroeTest.content}
      </div>
 </div>

@action包裹的情况

export default class DemoStore {
    // 被观察的属性
    @observable content = ''

     @action test(){
        console.log('123');
        this.content = 'test again';
        console.log('content:'+this.content);
    }
}

/******************************************************/

const store3 = new DemoStore();
...

<div>
                <div>test3测试:</div>
                <Button onClick={store3.test.bind(this)}>test</Button>
                <div style={{marginBottom:'100px'}}>{store3.content}</div>
</div>

测试:

  • onClick={()=>store3.test()}无报错,内容正常显示
  • onClick={store3.test} 可以打印123,但是找不到content的值
  • onClick={store3.test.bind(this) 可以打印123,可以修改content的值,但是视图中的内容无法显示,似乎失去可监听(因为bind会生成一个新的函数,新生成的store3.test和下面的store.content可能指向不一了,不知道和这个是否有关)

最新的测试发现,如果@action包裹的函数写成箭头函数的形式,则组件中的调用可以不需要再外边包裹一层匿名函数