【问题标题】:MobX Observer component not reacting to change in ObservableMobX Observer 组件对 Observable 中的更改没有反应
【发布时间】:2021-11-22 20:19:39
【问题描述】:

我一直在摆弄 MobX,并且很难理解为什么以下代码 sn-p 中的 ChildComponent 对状态更新没有反应。

我的理解是ChildComponent 应该更新,因为每次调用controller.updateState() 后isOpen.get() 都会发生变化(这是通过按钮单击促成的)。我添加了一些日志语句,发现状态 确实 正确更新,但 ChildComponent 中的文本没有,我无法弄清楚原因。如果能帮助我理解我在这里做错了什么,我将不胜感激。

注意:我知道从 MobX v6 开始需要调用 makeObservable。但是,我正在处理的代码库使用不支持该函数调用的旧版本。

App.tsx:

import { computed } from "mobx";
import { observer } from "mobx-react";
import { Controller } from "./controller";

const ChildComponent = observer(({ isOpen }: { isOpen: boolean }) => (
  <p>isOpen: {isOpen.toString()}</p>
));

export default function App() {
  const controller = new Controller();

  const isOpen = computed(() => controller.state === "open");

  const onClick = () => {
    if (isOpen.get()) {
      controller.updateState("closed");
    } else {
      controller.updateState("open");
    }
  };

  return (
    <div className="App">
      <ChildComponent isOpen={isOpen.get()} />
      <button onClick={onClick}>Toggle state</button>
    </div>
  );
}

controller.ts:

import { action, observable } from "mobx";

type State = "open" | "closed";

export class Controller {

  @observable.ref
  state: State;

  constructor() {
    this.state = "open";
  }

  @action
  updateState = (newState: State) => {
    this.state = newState;
  };
}

codeandbox 链接:https://codesandbox.io/s/broken-pine-3kwpt?file=/src/App.tsx

【问题讨论】:

    标签: reactjs typescript mobx


    【解决方案1】:

    那里出了很多问题:

    1. 使用makeObservable 或将示例降级到 MobX 版本 5,否则将无法正常工作

    2. 布尔值不需要使用@observable.ref,只需使用普通的普通@observable

    3. 你不能这样使用computed。 computed 是一个应该在你的商店内部使用的装饰器,类似于observable,像这样:

      @computed
      get isOpen() {
        return this.state === 'open';
      }
    
    1. 在您的示例中,App 应该包含在 observer 中,因为它取消了对可观察值 (isOpen) 的引用。并且每个执行它的组件都应该被包装。同时ChildComponent 将isOpen 属性作为原始值,因此它不会从observer 中受益(因为它没有引用任何可观察的属性)。

    2. 您需要以不同的方式创建控制器。现在你在每次渲染时重新创建它,即使你修复了上面的所有问题,它也不会起作用,因为每次你更改一些值时,App 都会重新渲染并使用默认值重新创建商店。

    希望它有意义!

    Working Codesandbox example with everything fixed

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-03-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多