如何在 React 组件卸载时停止 JavaScript 事件?

How to stop JavaScript events when React component unmounts?

背景:
我有一个用 React 构建的网络应用程序(当前版本为 16.4.2)。它只会在触摸屏上使用。它由大量用于执行操作的按钮组成,由于都是触摸式的,因此我使用 touchstart/touchend 来处理这些操作。

示例: 这是我如何使用事件的基本示例。你点击一个按钮,它将 this.state.exampleRedirect 设置为 true,这反过来又使组件重新渲染,然后转到新页面(使用 react-router-dom)。一切正常。

<button
  type='button'
  onTouchStart={() => this.setState({ exampleRedirect: true })}
  className='o-button'>
  Open modal
</button>

问题:
我最初使用 onClick 来处理按钮,但遇到了问题,因为我的用户手指粗,技术背景不多,当他们触摸按钮时,他们会将手指拖到按钮上,但不会触发点击. OnTouchStart 通过在发生任何触摸(拖动、滑动、点击等)时触发来解决此问题。

问题出在 onTouchStart 上。用户触摸按钮,它会快速更改页面(使用路由器)并重新呈现新页面。该应用程序速度很快,所以这几乎是瞬时的,这意味着当新页面加载时,用户的手指通常仍在屏幕上,因此会在他们触摸的任何地方触发另一个触摸事件。这通常是另一个路由按钮,因此它只会通过屏幕触发,直到他们抬起手指。

我正在通过在每次页面加载时延迟启用按钮来解决这个问题。

// example component
import React, { Component } from 'react';

class ExampleComponent extends Component {
  state = { buttonsDisabled: true }

  // after 300ms, the buttons are set to enabled (prevents touch events 
  // from firing when the page first loads
  componentWillMount() {
    timeoutId = setTimeout(() => {
      this.setState({ buttonsDisabled: false });
    }, 300);
  }

  render() {
    return (
      // button in render method
      <button
        disabled={this.state.buttonsDisabled}
        type='button'
        onTouchStart={() => this.setState({ exampleRedirect: true })}
        className='o-button'>
        Open modal
      </button>
    );
  }

有没有更好的方法?还是一种做我正在做的事情的方法,但在全球范围内,所以我不必在大约 100 个组件中添加这个简陋的代码?

谢谢!

不使用 onTouchStart 事件(当触摸点放在触摸表面上时触发)并使用超时,这有点 hack,您应该使用 onTouchEnd 因为它会在触摸点从触摸表面移开时触发,从而确保不会发生上述情况。

// example component
import React, { Component } from 'react';

class ExampleComponent extends Component {
  state = { buttonsDisabled: true }

  // after 300ms, the buttons are set to enabled (prevents touch events 
  // from firing when the page first loads
  componentWillMount() {
    timeoutId = setTimeout(() => {
      this.setState({ buttonsDisabled: false });
    }, 300);
  }

  render() {
    return (
      // button in render method
      <button
        disabled={this.state.buttonsDisabled}
        type='button'
        onTouchEnd={() => this.setState({ exampleRedirect: true })}
        className='o-button'>
        Open modal
      </button>
    );
  }