React plugin that addresses iOS's 300ms tap delay by injecting a TapEventPlugin into React's event system
npx @tessl/cli install tessl/npm-react-tap-event-plugin@3.0.0React 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.
npm install react-tap-event-pluginvar injectTapEventPlugin = require("react-tap-event-plugin");ES6 import (if using transpilation):
import injectTapEventPlugin from "react-tap-event-plugin";var injectTapEventPlugin = require("react-tap-event-plugin");
var React = require("react");
var ReactDOM = require("react-dom");
// Inject the plugin once, early in your app lifecycle
injectTapEventPlugin();
var Main = React.createClass({
render: function() {
return (
<a
href="#"
onTouchTap={this.handleTouchTap}
onTouchTapCapture={this.handleTouchTapCapture}
onClick={this.handleClick}>
Tap Me
</a>
);
},
handleClick: function(e) {
console.log("click", e);
},
handleTouchTap: function(e) {
console.log("touchTap", e);
},
handleTouchTapCapture: function(e) {
console.log("touchTapCapture", e);
}
});
ReactDOM.render(<Main />, document.getElementById("container"));The main functionality is injecting the tap event plugin into React's internal event system.
/**
* Injects the TapEventPlugin into React's event system to handle tap events
* Must be called once per application lifecycle, before ReactDOM.render()
*
* @param {Object} strategyOverrides - Optional configuration object
* @param {Function} strategyOverrides.shouldRejectClick - Custom click rejection strategy function
* @throws {Error} In development mode, throws if called multiple times
*/
function injectTapEventPlugin(strategyOverrides);Usage Examples:
// Basic injection with default settings
injectTapEventPlugin();
// Advanced: Custom click rejection strategy
injectTapEventPlugin({
shouldRejectClick: function(lastTouchEventTimestamp, clickEventTimestamp) {
// Always reject clicks (touch-only mode)
return true;
}
});
// Advanced: Longer click rejection window
injectTapEventPlugin({
shouldRejectClick: function(lastTouchEventTimestamp, clickEventTimestamp) {
// Reject clicks within 1000ms instead of default 750ms
return lastTouchEventTimestamp && (clickEventTimestamp - lastTouchEventTimestamp) < 1000;
}
});Once injected, components can use the onTouchTap event handler.
/**
* Touch tap event properties available in event handlers
* This is a SyntheticEvent that follows React's standard event interface
*/
interface TouchTapEvent {
/** Event type - always 'touchTap' */
type: string;
/** The target element that received the tap */
target: HTMLElement;
/** Current target (may differ from target during event bubbling) */
currentTarget: HTMLElement;
/** Event phase (1=capturing, 2=target, 3=bubbling) */
eventPhase: number;
/** Whether the event bubbles */
bubbles: boolean;
/** Whether the event can be cancelled */
cancelable: boolean;
/** Timestamp when the event occurred */
timeStamp: number;
/** Whether default action was prevented */
defaultPrevented: boolean;
/** Whether the event is trusted */
isTrusted: boolean;
/** Prevent the default browser behavior */
preventDefault(): void;
/** Stop event propagation to parent elements */
stopPropagation(): void;
/** Persist the event object (prevent pooling) */
persist(): void;
}/**
* Configuration object for customizing plugin behavior
*/
interface StrategyOverrides {
/**
* Custom function to determine if a click event should be rejected
* @param lastTouchEventTimestamp - Timestamp of the last touch event (number)
* @param clickEventTimestamp - Timestamp of the click event to evaluate (number)
* @returns {boolean} - true if click should be rejected, false otherwise
*/
shouldRejectClick?: (lastTouchEventTimestamp: number, clickEventTimestamp: number) => boolean;
}The plugin includes a built-in strategy for rejecting ghost clicks:
/**
* Default click rejection strategy
* Rejects click events that occur within 750ms of a touch event
*
* @param {number} lastTouchEvent - Timestamp of last touch event
* @param {number} clickTimestamp - Timestamp of click event to evaluate
* @returns {boolean} - true if click should be rejected
*/
function defaultClickRejectionStrategy(lastTouchEvent, clickTimestamp);The plugin works by:
touchstart, touchend, touchcancel, and touchmove eventstouchTap events that bubble through React's event systemThe plugin includes several safety mechanisms:
injectTapEventPlugin() is called multiple times