React provides an easy way to manage events. Prepare to say goodbye to addEventListener
🙂
In the previous article about the State you saw this example:
const CurrencySwitcher = (props) => {
return (
<button onClick={props.handleChangeCurrency}>
Current currency is {props.currency}. Change it!
</button>
)
}
If you’ve been using JavaScript for a while, this is just like plain old JavaScript event handlers. But this time you’re defining everything in JavaScript, not in your HTML, and you’re passing a function, not a string.
The actual event names are a little bit different, because in React you use camelCase for everything. So onclick
becomes onClick
, onsubmit
becomes onSubmit
.
For reference, this is old school HTML with JavaScript events mixed in:
<button onclick="handleChangeCurrency()"> ... <;/button>
Event handlers
It’s a convention to have event handlers defined as methods on the Component class:
class Converter extends React.Component { handleChangeCurrency = (event) => { this.setState({ currency: this.state.currency === '€' ? '$' : '€' }) } }
All handlers receive an event object that adheres, cross-browser, to the W3C UI Events spec.
Bind this
in methods
Don’t forget to bind methods. The methods of ES6 classes by default are not bound. What this means is that this
is not defined unless you define methods as
class Converter extends React.Component {
handleClick = (e) => { /* ... */ }
//...
}
when using the the property initializer syntax with Babel (enabled by default in create-react-app
).
Otherwise you need to bind it manually in the constructor:
class Converter extends React.Component {
constructor(props) {
super(props);
this.handleClick = this.handleClick.bind(this);
}
handleClick(e) {}
}
The events reference
There are lots of events supported, so here’s a summary list.
Clipboard
- onCopy
- onCut
- onPaste
Composition
- onCompositionEnd
- onCompositionStart
- onCompositionUpdate
Keyboard
- onKeyDown
- onKeyPress
- onKeyUp
Focus
- onFocus
- onBlur
Form
- onChange
- onInput
- onSubmit
Mouse
- onClick
- onContextMenu
- onDoubleClick
- onDrag
- onDragEnd
- onDragEnter
- onDragExit
- onDragLeave
- onDragOver
- onDragStart
- onDrop
- onMouseDown
- onMouseEnter
- onMouseLeave
- onMouseMove
- onMouseOut
- onMouseOver
- onMouseUp
Selection
- onSelect
Touch
- onTouchCancel
- onTouchEnd
- onTouchMove
- onTouchStart
UI
- onScroll
Mouse Wheel
- onWheel
Media
- onAbort
- onCanPlay
- onCanPlayThrough
- onDurationChange
- onEmptied
- onEncrypted
- onEnded
- onError
- onLoadedData
- onLoadedMetadata
- onLoadStart
- onPause
- onPlay
- onPlaying
- onProgress
- onRateChange
- onSeeked
- onSeeking
- onStalled
- onSuspend
- onTimeUpdate
- onVolumeChange
- onWaiting
Image
- onLoad
- onError
Animation
- onAnimationStart
- onAnimationEnd
- onAnimationIteration
Transition
- onTransitionEnd
React’s Declarative approach
You’ll run across articles describing React as a declarative approach to building UIs.
See declarative programming to read more about declarative programming.
React declarative approach
React made its “declarative approach” quite popular and upfront so it permeated the frontend world along with React.
It’s really not a new concept, but React made building UIs a lot more declarative than with HTML templates. You can build Web interfaces without even touching the DOM directly, and you can have an event system without having to interact with the actual DOM Events.
For example, looking up elements in the DOM using jQuery or DOM events is an iterative approach.
React’s declarative approach abstracts that for us. We just tell React we want a component to be rendered in a specific way, and we never have to interact with the DOM to reference it later.
The Virtual DOM
Many existing frameworks, before React came on the scene, were directly manipulating the DOM on every change.
The “real” DOM
What is the DOM, first of all? The DOM (Document Object Model) is a Tree representation of the page, starting from the <ht
ml> tag, going down into each of the children, called nodes.
It’s kept in the browser memory, and directly linked to what you see in a page. The DOM has an API that you can use to traverse it, access every single node, filter them, and modify them.
The API is the familiar syntax you have likely seen many times, if you were not using the abstract API provided by jQuery and friends:
document.getElementById(id)
document.getElementsByTagName(name)
document.createElement(name)
parentNode.appendChild(node)
element.innerHTML
element.style.left
element.setAttribute()
element.getAttribute()
element.addEventListener()
window.content
window.onload
window.dump()
window.scrollTo()
React keeps a copy of the DOM representation, because the Virtual DOM concerns the React rendering.
The Virtual DOM
Every time the DOM changes, the browser has to do two intensive operations: repaint (visual or content changes to an element that do not affect the layout and positioning relative to other elements) and reflow (recalculate the layout of a portion of the page — or the whole page layout).
React uses a Virtual DOM to help the browser use fewer resources when changes need to be made on a page.
When you call setState()
on a Component, specifying a state different than the previous one, React marks that Component as dirty. This is key: React only updates when a Component changes the state explicitly.
What happens next is:
- React updates the Virtual DOM relative to the components marked as dirty (with some additional checks, like triggering
shouldComponentUpdate()
) - Runs the diffing algorithm to reconcile the changes
- Updates the real DOM
Why is the Virtual DOM helpful: batching
The key thing is that React batches much of the changes and performs a unique update to the real DOM. It does this by changing all the elements that need to be changed at the same time, so the repaint and reflow the browser must perform to render the changes are executed just once.