如何处理 class 构造函数中定义的反应?

How do you dispose a reaction defined in a class constructor?

在我的一些模型中,我需要像这样在构造函数中定义一个反应:

constructor() {

    //...some code

    const dispose = reaction(
        () => this.items.length,
        count => {
            this.setItemCount(count);
        }
    );

}

我使用的是反应而不是计算 (@computed get itemCount()),因为将 items 加载到状态是一项昂贵的操作(通过网络传输大量数据),因此我需要保留最近的值,以便它可以在整个应用程序中使用。如果在项目加载到状态时计数发生变化,则反应是更新值。

所以,考虑到上述情况,我想知道 when/how 我会处理反应吗?我想避免内存泄漏。尽管我更喜欢反应式方法而不是命令式方法,但我愿意接受其他方法来完成我需要的事情。

我正在使用一系列一次性物品 + 特定方法来处理它们。 它看起来像:

class MyClass {
  ...
  disposables = [];
  ...
  constructor () {
    // constructor stuff

    this.disposables.push(reaction(
      () => this.items.length,
      count => {
        this.setItemCount(count);
      }
    ))
  }
  ...
  disposeAll = () => {
    this.disposables.forEach(dispose => dispose());
  }
}

如果你想处理特定的反应,这种方法是没有用的。但在这种情况下,您可以映射而不是数组。

三种方法。

  1. 反应完成后处理它。
constructor() {

   const dispose = reaction(
       () => this.items.length,
       (count, reaction) => {
           this.setItemCount(count);
           if(count === 100) reaction.dispose() 
       }
   );

} 
  1. 其他一些操作会为您处理它。就像一个按钮点击。或者另一种反应。实际上,无论您需要什么。

class myStore {
 disposer

 constructor() {
   this.disposer = reaction(
       () => this.items.length,
       (count) => this.setItemCount(count)
   );
 }

 myButtonClick = () => {
   this.disposer()
 }
}
  1. 在您的 class 中创建一个 "deconstructor" 方法,当您不再 "need" 此 class/store 时将调用该方法。在安全地将东西传递给垃圾收集器之前,您可以使用此方法倾倒任何需要清理的东西。
class myStore {

  disposers = []

  constructor () {
    this.disposers.push(reaction(
        () => this.items.length,
        (count, reaction) => {
            this.setItemCount(count);
            if(count === 100) reaction.dispose() 
        }
    ))
  }

  deconstructor() {
        this.disposers.forEach((disposer) => disposer())
  }

}

你也有责任调用这个解构函数。通常您会在组件卸载时调用它。下面的挂钩示例:

function Example() {

  const [store] = useState(() => new myStore())

  useEffect(() => {
    return () => store.deconstructor()
  }, [])

  return <App/>
}

如果store是global/context,你可以在frame组件(应用程序生命周期中一直挂载的组件)中调用析构函数,所以当用户退出应用程序时它是运行。然而,我不太确定,这个步骤对于 Mobx 一次性用品的需求有多大,也许有人可以对此发表评论。不过这样做并没有什么坏处。

注意。实际上,无论如何您都应该始终执行第 3 项,因为可能由于某些原因,条件 1.(或 2.)可能无法触发并且您在后台留下不必要的反应滴答作响。