当 'action'/'runInAction' 在 mobx react 中确实需要时

When 'action'/'runInAction' is really needed in mobx react

有人可以向我解释真正的区别是什么以及为什么这里的两个示例工作相同:

1) 通过 action/runInAction 在存储文件中更改可观察状态:

颜色存储文件:

@observable
color='red'

@action
setColor(){
  this.color='blue'
}

2)通过组件本身改变状态(这被认为是不好的做法):

React 组件文件:

onClick = () => this.props.colorStore.color='blue' //still working...

差异更多地与约定和编写干净可维护的代码有关,而不是程序的行为。所以:

  1. 您正在 变异 在您的 UI 组件中存储数据。这是不正确的,因为 UI 应该只 可视化 数据并处理例如用户操作,然后将其转换为特定操作数据存储(在您的情况下更新颜色)。 商店负责管理此数据状态
  2. 所有 observable 数据被认为是一种很好的做法,仅在 actionsmutated。为什么?因为变异数据的单一来源是明确的 - 仅在操作中并且仅在数据层(商店)中。该代码不太容易出错和不清楚状态管理,最大的好处是如果您打开 use strict 模式
  3. ,您可以强制您的应用程序不构建

Mobx action 正在执行 批处理 ,类似于 ReactJS 批处理多个更改的方式。

当您使用 reactjs click 处理程序时,react 会自动批处理其中发生的更改,因此您不会多次看到组件渲染,但是,如果您从其他事件调用 setColor,假设在加载一些数据后,多次调用更改 setColor 中的可观察对象,这将触发观察者三次,组件将被渲染三次。

当你用 @action 装饰器包装你的函数或者你使用 runInAction 函数时,只有最后一个值将被使用(下面代码中的 green )并且组件将是只渲染一次。

setColor(){
  // this will render three times
  this.color='blue'
  this.color='red'
  this.color='green'
}

仅响应一次的 vanilla mobx 示例:

import { runInAction, observable, reaction, toJS } from "mobx";

const test = observable({
  name: "sonic",
  nick: "speed demon"
});

// console.log will be called only once with the value "name: 3"
reaction(
  () => toJS(test),
  data => console.log(`name: ${data.name}`)
);

runInAction(() => {
  test.name = "1";
  test.name = "2";
  test.name = "3";
});

查看 codesandbox

另请查看 github 回购上的讨论:is @action really necessary?