Handling User Events
NOTE: Some of the below code examples and explanations have been reproduced from sections of the official online documentation for React.
Handling events in React is very similar to handling events on DOM elements using properties like onclick. However, there are some differences, ie:
- React events are named using camelCase, rather than lowercase.
- With JSX you pass a function as the event handler, rather than a string.
For example, the HTML:
<button onclick="processClick()">Click Me!</button>
is slightly different in React:
<button onClick={processClick}>Click me!</button>
To see this in action, let's code a simple "click counter" component that renders a single button that shows a number that increases by one (1) every time it's clicked. To achieve this, we'll create a new component called "ClickCounter":
import { useState } from 'react';
export default function ClickCounter(props) {
const [numClicks, setNumClicks] = useState(0);
function increaseNumClicks(e) { // 'e' is the current event object
setNumClicks(numClicks + 1);
}
return <button onClick={increaseNumClicks}>Clicks: {numClicks}</button>
}
NOTE: Be careful when updating state based on a previous value (ie: numClicks + 1 in the example above), as it may not always work as expected on types that are not primitive, ie: "string", "number", "boolean", etc. For example, if we use the same logic to add an element to a state value holding an array, we may be tempted to use the following code:
setMyArray(myArray.push('new element'));
However, updating state in this manner will not cause the component to re-render. Instead, we must provide a new array, ie:
setMyArray([...myArray, 'new element']);
For more information see: Updating arrays in state and Updating objects in state
Here, you will notice that we have added a couple new concepts to the construction and rendering of a typical functional component, ie:
We have declared a function to handle the event. It receives a single parameter 'e' which is a "synthetic event" - "a cross-browser wrapper around the browser’s native event. It has the same interface as the browser’s native event, including stopPropagation() and preventDefault(), except the events work identically across all browsers."
On our button element, we use "onClick" (instead of "onclick") to reference the event handler and "wire up" the event.
NOTE: For a full list events please refer to the official documentation for supported events.
Adding Parameters
As you can see from the above example, our callback function "increaseNumClicks" is registered to the onClick event by passing the function only - the function is not actually invoked anywhere in our JSX. This works fine, but what if we wish to pass one or more parameters to the function, in addition to the SyntheticEvent (above)?
This can actually be achieved by registering the event as an anonymous function declared within the JSX, which invokes the callback function. For example:
function increaseNumClicks(e, message) { // 'e' is the current event object
console.log(message);
setNumClicks(numClicks + 1);
}
return <button onClick={(e) => { increaseNumClicks(e, "Hello") }}>Clicks: {numClicks}</button>
Here, we declare the callback function in place. It accepts a single parameter "e" as before, but the body of the function invokes the callback function. This allows us to continue to pass the SyntheticEvent (e) to our event handler "increaseNumClicks" as well as add any other parameter values.