为什么计算的记录是两次而不是三次?

  • 根据官方的mobx文档,我了解到,当我们用@action包装react事件处理程序时,我们应该看到应该对mobx派生的fns进行批处理-计算的fns,反应执行器fns,自动运行的fns。
  • 如果我们以它为例,它是这样的:

情况1:当React事件处理程序包含动作时

import React, { Component } from "react";
import { render } from "react-dom";
import { observable, action, computed, autorun } from "mobx";
import { observer } from "mobx-react";

class Person {
  @observable firstName = "Ramu";
  @observable lastName = "Ratnam";
  @observable initial = "K";

  @computed get fullName() {
    console.log("Computed");
    return this.firstName + " " + this.lastName + " " + this.initial;
  }

  @action
  changeFirstNameAndLastName = (firstName, lastName) => {
    this.firstName = "Mark";
    this.lastName = "Wayne";
    this.initial = "J";
  };

}

const newPerson = new Person();

// Reaction: log the profile info whenever it changes

// Example React component that observes state
const ProfileView = observer(props => {
  console.log("render ProfileView");

  return (
    <div>
      <p>{props.person.fullName}</p>
      <button onClick={props.person.changeFirstNameAndLastName}>
        Change first name and last name
      </button>
    </div>
  );
});

render(<ProfileView person={newPerson} />, document.getElementById("root"));

  • When user presses Change first name and last name button then due to batching the computed, ProfileView render fn should be triggered once, which is as expected

  • When we remove @action to the changeFirstNameAndLastName handler as the batching does not happen for the computed fn it should be triggered thrice and render fn should be triggered once This is not happening. Instead computed fn is being triggered twice. Check case 2 snippet for the same.

为什么?需要解释。

情况2:React事件处理程序未包装动作时

import React, { Component } from "react";
import { render } from "react-dom";
import { observable, action, computed, autorun } from "mobx";
import { observer } from "mobx-react";

class Person {
  @observable firstName = "Ramu";
  @observable lastName = "Ratnam";
  @observable initial = "K";

  @computed get fullName() {
    console.log("Computed");
    return this.firstName + " " + this.lastName + " " + this.initial;
  }

  changeFirstNameAndLastName = (firstName, lastName) => {
    this.firstName = "Mark";
    this.lastName = "Wayne";
    this.initial = "J";
  };

}

const newPerson = new Person();

// Reaction: log the profile info whenever it changes

// Example React component that observes state
const ProfileView = observer(props => {
  console.log("render ProfileView");

  return (
    <div>
      <p>{props.person.fullName}</p>
      <button onClick={props.person.changeFirstNameAndLastName}>
        Change first name and last name
      </button>
    </div>
  );
});

render(<ProfileView person={newPerson} />, document.getElementById("root"));
注意:另外,我在react类组件中实现了相同的代码段,并且怪异的行为仍然存在。请参见下面的代码段。

import React, { Component } from "react";
import { render } from "react-dom";
import { observable, computed, autorun } from "mobx";
import { observer } from "mobx-react";

// Example React component that observes state
@observer
class ProfileView extends Component {
  @observable firstName = "Ramu";
  @observable lastName = "Ratnam";
  @observable initial = "K";

  @computed get fullName() {
    console.log("Computed");
    return this.firstName + " " + this.lastName + " " + this.initial;
  }

  changeFirstNameAndLastName = (firstName, lastName) => {
    this.firstName = "Mark";
    this.lastName = "Wayne";
    this.initial = "J";
  };

  render() {
    console.log("render ProfileView");

    return (
      <div>
        <p>{this.fullName}</p>
        <button onClick={this.changeFirstNameAndLastName}>
          Change first name and last name
        </button>
      </div>
    );
  }
}

render(<ProfileView />, document.getElementById("root"));