or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

tessl/npm-react-tap-event-plugin

React plugin that addresses iOS's 300ms tap delay by injecting a TapEventPlugin into React's event system

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
npmpkg:npm/react-tap-event-plugin@3.0.x

To install, run

npx @tessl/cli install tessl/npm-react-tap-event-plugin@3.0.0

0

# React Tap Event Plugin

1

2

React Tap Event Plugin is a deprecated React plugin that addresses iOS's dreaded 300ms tap delay by injecting a TapEventPlugin into React's event system. It enables developers to use `onTouchTap` and `onTouchTapCapture` events instead of `onClick` to avoid mobile tap delays, though it has been deprecated since React 16.4 as modern browsers have largely resolved the original delay issue.

3

4

## Package Information

5

6

- **Package Name**: react-tap-event-plugin

7

- **Package Type**: npm

8

- **Language**: JavaScript

9

- **Installation**: `npm install react-tap-event-plugin`

10

- **Compatibility**: React 16.0.0 to < 16.4.0

11

- **Status**: Deprecated (use only for legacy browser support)

12

13

## Core Imports

14

15

```javascript

16

var injectTapEventPlugin = require("react-tap-event-plugin");

17

```

18

19

ES6 import (if using transpilation):

20

21

```javascript

22

import injectTapEventPlugin from "react-tap-event-plugin";

23

```

24

25

## Basic Usage

26

27

```javascript

28

var injectTapEventPlugin = require("react-tap-event-plugin");

29

var React = require("react");

30

var ReactDOM = require("react-dom");

31

32

// Inject the plugin once, early in your app lifecycle

33

injectTapEventPlugin();

34

35

var Main = React.createClass({

36

render: function() {

37

return (

38

<a

39

href="#"

40

onTouchTap={this.handleTouchTap}

41

onTouchTapCapture={this.handleTouchTapCapture}

42

onClick={this.handleClick}>

43

Tap Me

44

</a>

45

);

46

},

47

48

handleClick: function(e) {

49

console.log("click", e);

50

},

51

52

handleTouchTap: function(e) {

53

console.log("touchTap", e);

54

},

55

56

handleTouchTapCapture: function(e) {

57

console.log("touchTapCapture", e);

58

}

59

});

60

61

ReactDOM.render(<Main />, document.getElementById("container"));

62

```

63

64

## Capabilities

65

66

### Plugin Injection

67

68

The main functionality is injecting the tap event plugin into React's internal event system.

69

70

```javascript { .api }

71

/**

72

* Injects the TapEventPlugin into React's event system to handle tap events

73

* Must be called once per application lifecycle, before ReactDOM.render()

74

*

75

* @param {Object} strategyOverrides - Optional configuration object

76

* @param {Function} strategyOverrides.shouldRejectClick - Custom click rejection strategy function

77

* @throws {Error} In development mode, throws if called multiple times

78

*/

79

function injectTapEventPlugin(strategyOverrides);

80

```

81

82

**Usage Examples:**

83

84

```javascript

85

// Basic injection with default settings

86

injectTapEventPlugin();

87

88

// Advanced: Custom click rejection strategy

89

injectTapEventPlugin({

90

shouldRejectClick: function(lastTouchEventTimestamp, clickEventTimestamp) {

91

// Always reject clicks (touch-only mode)

92

return true;

93

}

94

});

95

96

// Advanced: Longer click rejection window

97

injectTapEventPlugin({

98

shouldRejectClick: function(lastTouchEventTimestamp, clickEventTimestamp) {

99

// Reject clicks within 1000ms instead of default 750ms

100

return lastTouchEventTimestamp && (clickEventTimestamp - lastTouchEventTimestamp) < 1000;

101

}

102

});

103

```

104

105

### Touch Tap Event Handling

106

107

Once injected, components can use the `onTouchTap` event handler.

108

109

```javascript { .api }

110

/**

111

* Touch tap event properties available in event handlers

112

* This is a SyntheticEvent that follows React's standard event interface

113

*/

114

interface TouchTapEvent {

115

/** Event type - always 'touchTap' */

116

type: string;

117

/** The target element that received the tap */

118

target: HTMLElement;

119

/** Current target (may differ from target during event bubbling) */

120

currentTarget: HTMLElement;

121

/** Event phase (1=capturing, 2=target, 3=bubbling) */

122

eventPhase: number;

123

/** Whether the event bubbles */

124

bubbles: boolean;

125

/** Whether the event can be cancelled */

126

cancelable: boolean;

127

/** Timestamp when the event occurred */

128

timeStamp: number;

129

/** Whether default action was prevented */

130

defaultPrevented: boolean;

131

/** Whether the event is trusted */

132

isTrusted: boolean;

133

134

/** Prevent the default browser behavior */

135

preventDefault(): void;

136

/** Stop event propagation to parent elements */

137

stopPropagation(): void;

138

/** Persist the event object (prevent pooling) */

139

persist(): void;

140

}

141

```

142

143

## Types

144

145

### Strategy Override Configuration

146

147

```javascript { .api }

148

/**

149

* Configuration object for customizing plugin behavior

150

*/

151

interface StrategyOverrides {

152

/**

153

* Custom function to determine if a click event should be rejected

154

* @param lastTouchEventTimestamp - Timestamp of the last touch event (number)

155

* @param clickEventTimestamp - Timestamp of the click event to evaluate (number)

156

* @returns {boolean} - true if click should be rejected, false otherwise

157

*/

158

shouldRejectClick?: (lastTouchEventTimestamp: number, clickEventTimestamp: number) => boolean;

159

}

160

```

161

162

### Default Click Rejection Strategy

163

164

The plugin includes a built-in strategy for rejecting ghost clicks:

165

166

```javascript { .api }

167

/**

168

* Default click rejection strategy

169

* Rejects click events that occur within 750ms of a touch event

170

*

171

* @param {number} lastTouchEvent - Timestamp of last touch event

172

* @param {number} clickTimestamp - Timestamp of click event to evaluate

173

* @returns {boolean} - true if click should be rejected

174

*/

175

function defaultClickRejectionStrategy(lastTouchEvent, clickTimestamp);

176

```

177

178

## Architecture

179

180

The plugin works by:

181

182

1. **Event System Integration**: Injects itself into React's internal EventPluginHub using private APIs

183

2. **Touch Event Detection**: Listens for `touchstart`, `touchend`, `touchcancel`, and `touchmove` events

184

3. **Tap Gesture Recognition**: Detects taps by measuring distance between touch start/end (within 10px threshold)

185

4. **Ghost Click Prevention**: Automatically rejects click events that follow touch events within 750ms

186

5. **Event Synthesis**: Creates synthetic `touchTap` events that bubble through React's event system

187

188

## Error Handling

189

190

The plugin includes several safety mechanisms:

191

192

- **Development Mode Protection**: Throws an invariant error if `injectTapEventPlugin()` is called multiple times

193

- **Production Mode Tolerance**: Silently ignores multiple injection attempts in production

194

- **Event Pooling**: Uses React's event pooling for memory efficiency

195

- **Graceful Degradation**: Falls back to regular click events if touch events are not available

196

197

## Browser Compatibility

198

199

- **Target Browsers**: Primarily iOS Safari and older mobile browsers with 300ms click delay

200

- **Modern Browser Note**: Most modern browsers have eliminated the 300ms delay, making this plugin unnecessary

201

- **React Version**: Compatible with React 16.0.0 to < 16.4.0 only

202

- **Deprecation**: Plugin is deprecated and will not work with React 16.4+

203

204

## Common Use Cases

205

206

1. **Legacy Mobile Support**: Supporting older mobile browsers that still have the 300ms delay

207

2. **Hybrid Apps**: React apps running in WebView containers (like Cordova/PhoneGap)

208

3. **Consistent Touch Response**: Ensuring immediate feedback for touch interactions across all mobile devices

209

4. **Touch-Only Interfaces**: Applications designed exclusively for touch devices