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

时间:2018-09-25 14:54:02

标签: javascript reactjs touch touchstart

背景
我有一个用React构建的Web应用程序(当前版本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。用户触摸该按钮,它将快速更改页面(使用路由器)并重新呈现新页面。该应用程序运行很快,因此几乎是瞬时的,这意味着在加载新页面时,用户的手指通常仍在屏幕上,从而在他们触摸的任何物体上触发ANOTHER触摸事件。这通常是另一个路由按钮,因此它会在屏幕上触发直到他们松开手指。

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

// 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个组件中添加此垃圾代码?

谢谢!

1 个答案:

答案 0 :(得分:1)

您应该使用onTouchStart来代替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> ); } 事件,并且使用超时(有点麻烦)当从触摸表面上移开触摸点时会触发,从而确保不会发生上述情况。

public class SomeService: ISomeService
{
  ...
  public async Task<Settings> GetSettings(UserIdentity user)
    {
        SettingsDBModel dbModel;
        using (DBHelperAsync dbHelper = new DBHelperAsync(user))
        {
            using (DBHelperReaderAsync reader = await dbHelper.ExecuteReader("Stored procedure Name", new { UserID = user.UserID }))
            {
                dbModel = await reader.GetResult<SettingsDBModel>();
            }
        }
        var settings = new Settings(dbModel);
        return settings;
    }
  ...
}