为什么 mobx 需要操作,为什么不直接将所有突变批量处理到 setImmediate 中?

Why mobx needs actions, why not just to batch all mutations into setImmediate?

提问人:Vasilii Rogin 提问时间:4/27/2018 更新时间:5/3/2018 访问量:1268

问:

我开始学习mobx,我不明白为什么mobx发明了“动作”实体。在 setImmediate 中将所有更改批量处理到下一个刻度中会更容易吗?这将自动使所有同步状态更改的行为方式与现在@action相同。在行动结束后立即触发观察者而不是在下一个价格变动中是否有任何好处?

MOBX的

评论


答:

1赞 Vasilii Rogin 5/3/2018 #1

根据 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 couple 也是如此。这意味着 React 组件在突变后不会立即重新渲染,只有在事件监听器回调后才会同步更新。

几个例子(所有 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>