为什么当我将 @action 装饰器添加到反应事件处理函数时组件没有重新渲染

Why does the component is not re-rendering when i add @action decorator to an react event handler function

问题:

当我将 @action 装饰器添加到 class 成员 fn 时,下面的反应组件不会重新呈现。

import { observable, action } from "mobx";
import { observer } from "mobx-react";
import * as React from "react";
import { render } from "react-dom";

@observer
class PriceCounter extends React.Component {
  @observable price = 0;

  @action
  setPrice = () => {
    this.price = this.price + 1;
  };

  @action
  currentPrice = () => {
    return this.price;
  }

  render() {
    return (
      <div>
        <span className="text-3xl">Total: {this.currentPrice()}</span>
        <button onClick={this.setPrice}>Change details</button>
      </div>
    );
  }
}

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

Why? Explanation needed.

要么你可以使用this.price来显示价格的更新值。或者你可以使用计算装饰器来做到这一点。

@observer
class PriceCounter extends React.Component {
  @observable price = 0;

  @action
  setPrice = () => {
    this.price = this.price + 1;
  };

  @computed
  get currentPrice() {
    return this.price;
  }

  render() {
    return (
      <div>
        <span className="text-3xl">Total: {this.currentPrice}</span>
        <button onClick={this.setPrice}>Change details</button>
      </div>
    );
  }
}

@observer
class PriceCounter extends React.Component {
  @observable price = 0;

  @action
  setPrice = () => {
    this.price = this.price + 1;
  };

  @action
  currentPrice = () => {
    return this.price;
  };

  render() {
    return (
      <div>
        <span className="text-3xl">Total: {this.price}</span>
        <button onClick={this.setPrice}>Change details</button>
      </div>
    );
  }
}

这是错误的操作用法。

@action 预计将围绕一个可观察量发生变化的函数进行包装。在这里,您没有更改 currentPrice 函数中的任何可观察值。

因为 render 是 mobx-react 中的一个跟踪函数,如果你没有用 action 包装 currentPrice 函数 & 如果你调用 this.currentPrice() mobx 跟踪那个函数中使用的可观察对象。

如果您正在使用带有动作的跟踪函数包装函数,mobx 不知道您是打算跟踪可观察对象还是想 运行 在函数执行后跟踪函数。

动作应该只并且总是用于修改状态的函数。看看When to use actions

在您提到的示例中,currentPrice 方法未修改状态。所以你不需要为此使用动作装饰器。