为什么mobx需要采取行动,为什么不将所有突变批量化为setImmediate?

时间:2018-04-26 21:38:59

标签: mobx

我开始学习mobx,我不明白为什么mobx发明了"动作"实体。将所有更改批量处理到setImmediate中的下一个tick会更容易吗?这将自动使所有同步状态更改的行为与@action现在一样。在行动结束后,而不是在下一个滴答声内,是否有利于触发观察者的权利?

1 个答案:

答案 0 :(得分:0)

根据https://github.com/mobxjs/mobx/issues/1523的对话:

  1. setImmediate仅在IE和Nodejs中实现。 setTimeout(fn,0)可能导致4 ms延迟
  2. https://hackernoon.com/the-fundamental-principles-behind-mobx-7a725f71f3e8:异步更新没有这么好的堆栈跟踪来查找触发更新的人
  3. React批处理只有来自事件侦听器的setState调用,所以mobx-react夫妇也是如此。这意味着React组件在变异后不会立即重新渲染,只有在事件监听器回调后才会同步更新。
  4. 几个例子(所有jsx组件都应该在@observer内):

    // Ok to do this
    <input value={appState.name} onChange={e => appState.name = e.target.value}/>
    
    
    // Ok too, will rerender only once
    <input value={appState.name} onChange={e => {
        appState.name = e.target.value; 
        appState.foo = appState.foo + 1;
    }}/>
    
    
    // Not very good, will rerender twice on each click.
    // Nevertheless, I do not know why someone will do this
    <button onClick={() => {
        setTimeout(() => {
            appState.foo = appState.foo + 1;
            appState.bar = appState.bar + 10;
        }, 0);
    }}>Click me foo={appState.foo} bar={appState.bar}</button>
    
    
    // But that way it will rerender once and show console output only once too
    autorun(() => console.info(`App state foo={appState.foo} bar={appState.bar}`));
    <button onClick={() => {
        setTimeout(() => {
            runInAction(() => {
                appState.bar = appState.bar + 10;
                appState.foo = appState.foo + 1;
            })
        }, 0);
    }}>Click me foo={appState.foo} bar={appState.bar}</button>
    
    
    // That code will show console output twice, but rerender only once
    autorun(() => console.info(`App state foo={appState.foo} bar={appState.bar}`));
    <button onClick={() => {
        setTimeout(() => {
            ReactDOM.unstable_batchedUpdates(() => {
                appState.bar = appState.bar + 10;
                appState.foo = appState.foo + 1;
            })
        }, 0);
    }}>Click me foo={appState.foo} bar={appState.bar}</button>