I am building a Minesweeper game with React and want to perform a different action when a cell is single or double clicked. Currently, the onDoubleClick
function will never fire, the alert from onClick
is shown. If I remove the onClick
handler, onDoubleClick
works. Why don’t both events work? Is it possible to have both events on an element?
/** @jsx React.DOM */ var Mine = React.createClass({ render: function(){ return ( <div className="mineBox" id={this.props.id} onDoubleClick={this.props.onDoubleClick} onClick={this.props.onClick}></div> ) } }); var MineRow = React.createClass({ render: function(){ var width = this.props.width, row = []; for (var i = 0; i < width; i++){ row.push(<Mine id={String(this.props.row + i)} boxClass={this.props.boxClass} onDoubleClick={this.props.onDoubleClick} onClick={this.props.onClick}/>) } return ( <div>{row}</div> ) } }) var MineSweeper = React.createClass({ handleDoubleClick: function(){ alert('Double Clicked'); }, handleClick: function(){ alert('Single Clicked'); }, render: function(){ var height = this.props.height, table = []; for (var i = 0; i < height; i++){ table.push(<MineRow width={this.props.width} row={String.fromCharCode(97 + i)} onDoubleClick={this.handleDoubleClick} onClick={this.handleClick}/>) } return ( <div>{table}</div> ) } }) var bombs = ['a0', 'b1', 'c2']; React.renderComponent(<MineSweeper height={5} width={5} bombs={bombs}/>, document.getElementById('content'));
Advertisement
Answer
Edit:
I’ve found that this is not an issue with React 0.15.3.
Original:
For React 0.13.3, here are two solutions.
1. ref callback
Note, even in the case of double-click, the single-click handler will be called twice (once for each click).
const ListItem = React.createClass({ handleClick() { console.log('single click'); }, handleDoubleClick() { console.log('double click'); }, refCallback(item) { if (item) { item.getDOMNode().ondblclick = this.handleDoubleClick; } }, render() { return ( <div onClick={this.handleClick} ref={this.refCallback}> </div> ); } }); module.exports = ListItem;
2. lodash debounce
I had another solution that used lodash
, but I abandoned it because of the complexity. The benefit of this was that “click” was only called once, and not at all in the case of “double-click”.
import _ from 'lodash' const ListItem = React.createClass({ handleClick(e) { if (!this._delayedClick) { this._delayedClick = _.debounce(this.doClick, 500); } if (this.clickedOnce) { this._delayedClick.cancel(); this.clickedOnce = false; console.log('double click'); } else { this._delayedClick(e); this.clickedOnce = true; } }, doClick(e) { this.clickedOnce = undefined; console.log('single click'); }, render() { return ( <div onClick={this.handleClick}> </div> ); } }); module.exports = ListItem;
on the soapbox
I appreciate the idea that double-click isn’t something easily detected, but for better or worse it IS a paradigm that exists and one that users understand because of its prevalence in operating systems. Furthermore, it’s a paradigm that modern browsers still support. Until such time that it is removed from the DOM specifications, my opinion is that React should support a functioning onDoubleClick
prop alongside onClick
. It’s unfortunate that it seems they do not.