React Mouse Events — Clicking, Dragging and Dropping, with Examples
If you’ve worked with Javascript, you’re likely familiar with events. Events are things that happen on a page that your code can detect and respond to. For example, onKeyDown can be used to detect keyboard inputs, and onSubmit can be used to detect form submissions.
One of React’s utilities is its events system, which normalizes the previously idiosyncratic ways that browsers treat events. Events are actually implemented on a per-browser basis, so Chrome’s DOMContentLoaded might trigger at a slightly different time than Opera’s DOMContentLoaded. React normalizes this behavior.
Today we’re going to look at one type of events — Mouse events — and examples of how they can be used in React. All of these events are available in vanilla Javascript as well (though occasionally with slightly different names), we’re just giving the examples in React JSX syntax.
React Event Syntax Example
Here’s one way you might use events in React:
We’re looking at JSX in a render’s return. It’s some kind of signup form, and it includes an onSubmit and three onChanges. We can see that when any of the text input fields are changed, the “handleInputChange” method is called, and when the form is submitted, the “handleSubmit” event is called.
Mouse Events
onClick
onClick is a common, useful event.
<button id=”create” onClick={this.createTable}>Create Table</button><button id=”cancel” onClick={this.cancelTable}>Cancel</button>
Here we’ve got two buttons, each with an onClick pointing to a corresponding event handler method. When you click the “Create Table” button, the “createTable” method will run.
onContextMenu
onContextMenu is similar but far less common — it listens for a right click rather than onClick’s left click.
<button onClick={this.handleClick} onContextMenu={this.handleContextMenu}>Click me!</button>
onDoubleClick
I’m sure you can guess.
<button onDoubleClick={this.handleDoubleClick>This would be good for emulating a desktop environment, I guess</button>
Note that if you have both an onClick and an onDoubleClick on the same element, the onDoubleClick won’t prevent the onClick from firing (twice)! You probably want to avoid that scenario.
onDrag
onDrag is for when the user is dragging the element. Since it fires continuously (every 350 ms) while the user is dragging, it’s a somewhat niche event case.
<div className="draggablediv" draggable="true" onDrag={this.handleDrag} onDoubleClick={this.handleDoubleClick}>This is even more like a desktop icon</div>
Some items (usually text, images and links, depending on the browser) can be dragged by default. The rest need “draggable=“true”” as above to function.
onDragStart, onDragEnd
These are for when the users begins dragging or finishes dragging (drops). They are likely to be important to any drag-and-drop functionality.
<div className="draggablediv" draggable="true" onDragStart={this.handleDragStart} onDragEnd={this.handleDragEnd}>Maybe I'm a ball?</div>
There are two important things to note here. First of all, onDragStart, onDrag, and onDragEnd all have the element being dragged as the event target.
Second, this is not yet enough to actually functionally drop an element in a new location. When you let go of the mouse, onDragEnd will fire, but the element will just snap back to wherever it started.
onDragEnter, onDragOver, onDragLeave
While the previous three drag events fire on the element being dragged, these three are attached to and fire on elements under the element being dragged. Say for instance you wanted to change an icon or an element’s color to indicate that it was being dragged over.
<div onDragOver={this.handleDragOver} onDragEnter={this.handleDragEnter} onDragExit={this.handleDragExit}>
I'm a box or an icon or something. Not the thing being dragged but the thing being dragged over.
</div>
In order for these to work, though, the element has to be specified as a valid drop zone. This is actually done with e.preventDefault()!
handleDragLeave = event => {
event.stopPropogation()
event.preventDefault()
};
handleDragOver = event => {
event.stopPropogation()
event.preventDefault()
};
handleDragEnter = event => {
event.stopPropogation()
event.preventDefault()
};
return (
<div className={'endzone'} onDragOver={this.handleDragOver} onDragEnter={this.handleDragEnter} onDragLeave={this.handleDragLeave}>
<p>The Drop Zone</p>
</div>
);
We’ve created a moving football and a landing zone, there’s just one key event left.
onDrop
onDrop is what allows us to drop! Like the previous three, it’s attached to the drop zone, not the dragging item. We need to preventdefault here as well, and then depending on what you’re dragging and dropping, we’ll want to do something like render an image or initiate a file transfer.
handleDragLeave = event => {
event.stopPropogation()
event.preventDefault()
// Bring the endzone back to normal, maybe?
};
handleDragOver = event => {
event.stopPropogation()
event.preventDefault()
// Turn the endzone red, perhaps?
};
handleDragEnter = event => {
event.stopPropogation()
event.preventDefault()
// Play a little sound, possibly?
};
handleDrop = event => {
event.stopPropogation()
event.preventDefault()
// Add a football image to the endzone, initiate a file upload,
// steal the user's credit card
};return (
<div className={'endzone'} onDragOver={this.handleDragOver} onDragEnter={this.handleDragEnter} onDragLeave={this.handleDragLeave} onDrop={this.handleDrop}>
<p>The Drop Zone</p>
</div>
);
The above is a full drop zone for a draggable element, just add draggable element. You could make a board game!
Join me next week for mouse movement events. You can make things follow your mouse, like the 90s web!