【问题标题】:Can't assign debounce to class property无法将 debounce 分配给类属性
【发布时间】:2018-12-07 22:36:14
【问题描述】:

我正在使用带有 Stage 2 预设的 Babel,并且有一个这样的 React 组件类:

class Test extends Component {
  someValue = 'Hello';

  componentDidMount() {
    this.debouncedHandleResize = debounce(this.handleResize, 1000);
    window.addEventListener('resize', this.debouncedHandleResize);
  }

  handleResize = () => {
    console.log(this.someValue);
  }
}

这按预期工作。窗口调整大小后 1000 毫秒,handleResize 方法触发并且控制台记录“Hello”。

为什么我不能执行以下操作?

class Test extends Component {
  someValue = 'Hello';

  debouncedHandleResize = debounce(this.handleResize, 1000);

  componentDidMount() {
    window.addEventListener('resize', this.debouncedHandleResize);
  }

  handleResize = () => {
    console.log(this.someValue);
  }
}

在这种情况下我得到一个错误:

TypeError: Expected a function

我一定遗漏了一些东西,但我认为这两种方法基本上都是为类分配属性值的方法。

【问题讨论】:

  • 看起来很奇怪你会多次处理handleResize....
  • 当我在堆栈 sn-p 中运行代码时,代码运行良好。
  • @epascarello 抱歉,我有几个错别字。我现在已经更正了。
  • console.log('this.handleResize', this.handleResize); debouncedHandleResize = debounce(this.handleResize, 1000);
  • debounce 不会导致您提到的错误,它没有这样的问题(除了您既没有绑定 debouncedHandleResize 也没有绑定handleResize)。考虑提供可以复制问题的stackoverflow.com/help/mcve

标签: javascript reactjs ecmascript-6 lodash debounce


【解决方案1】:

也许应该是:

class Test extends React.Component {
    ...
}

【讨论】:

  • 这可能确实是问题所在。至少这可以解释错误。
  • 抱歉,我的问题是一个错字。现在修好了。我仍然有同样的错误。看来我可以以标准方式将 debounce 函数绑定到类属性,但不能以新方式。
  • @Coop:正如我所说,您的代码在我测试时运行良好。仔细检查错字是否不在您的实际代码中。该错误适合(嗯,可能取决于您使用的浏览器)。
  • @FelixKling 感谢您的帮助,但这不是问题所在。我发现了问题所在,并将作为答案发布以帮助其他人。
【解决方案2】:

我发现了问题所在。在我的第二个示例(引发错误的示例)中,类属性设置如下:

debouncedHandleResize = debounce(this.handleResize, 1000);

该错误由于某种原因抱怨它不喜欢this.handleResize 并说它不是一个函数。虽然我不是 100% 理解这一点,但手动传入函数的简单测试消除了错误:

debouncedHandleResize = debounce(() => false, 1000);

有了这些知识,我编写课程的新方法是:

class Test extends Component {
  someValue = 'Hello';

  componentDidMount() {
    window.addEventListener('resize', this.handleResize);
  }

  handleResize = debounce(() => console.log(this.someValue), 1000)
}

【讨论】:

  • 现在您已经提供了实际代码,问题就很明显了。看我的回答。
【解决方案3】:

由于您更新了代码:问题是debouncedHandleResizehandleResize 都是公共类字段。因为debouncedHandleResize 分配首先出现,所以您试图在handleResize 存在之前引用它。

公共类字段是按顺序求值的,所以

class Test {
  debouncedHandleResize = debounce(this.handleResize, 1000);

  handleResize = () => {
    console.log(this.someValue);
  }
}

等价于

class Test {
  constructor() {
    this.debouncedHandleResize = debounce(this.handleResize, 1000);

    this.handleResize = () => {
      console.log(this.someValue);
    }
}

为什么这不起作用应该很明显。

解决方案

更改作业顺序:

class Test {
  handleResize = () => {
    console.log(this.someValue);
  }
  debouncedHandleResize = debounce(this.handleResize, 1000);
}

【讨论】:

  • 奇怪的是,我实际上并不知道这一点。因为我习惯于在构造函数中引用方法来绑定this,即使这些方法是在构造函数之后声明的。我猜在这种情况下,引用在方法内部,而不是在顶层。感谢您的帮助。
  • “即使这些方法是在构造函数之后声明的”,但“普通”类方法 (foo() {}) 是在原型上定义的,原型在执行构造函数时已经设置。这就是区别。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-11-17
  • 2019-04-30
  • 1970-01-01
  • 1970-01-01
  • 2014-06-04
  • 1970-01-01
相关资源
最近更新 更多