React Event Handling

Pro Members Only

This lesson is available if you have an active subscription.

Alternatively, some member might be able to gift it to you.

If you already have a subscription, you can sign in.

React Event Handling

Subscription Required

You must have an active subscription to access this content.
If you already have a subscription, you can sign in.

Basics of Handling Events in React

You can simply assign a function to any of the on* props for native HTML components e.g. onClick for a button

App.tsx
export default function App() {
const onButtonClick = () => {
console.log('Clicked');
};

return (
<div>
<button onClick={onButtonClick}>Click Me</button>
</div>
);
}

TypeScript types for Event Handlers

You can use an the type for the on* prop to ensure that our callback accepts well-typed arguments for any events that are passed in.

For example for button.onClick the type is React.MouseEventHandler<HTMLButtonElement>.

App.tsx
export default function App() {
const onClick: React.MouseEventHandler<HTMLButtonElement> = (event) => {
console.log("Clicked", { event }, { nativeEvent: event.nativeEvent });
};

return (
<div>
<button onClick={onClick}>Click Me</button>
</div>
);
}

Note that react wraps native events in a SyntheticEvent to ensure cross browser compatibility but you can still access the underlying event using event.nativeEvent. However for most cases the event object is what you should use.

Uncontrolled Form Elements

You can let input elements maintain their state internally by only providing an initial defaultValue. You can still listen to the value changes by using onChange event.

App.tsx
export default function App() {
return (
<div>
<input
defaultValue="Hi Fam!"
onChange={(e) => {
console.log(e.target.value);
}}
/>
</div>
);
}

Controlled Form Elements

If you wire the value of an input to a variable, the component is considered controlled. It's rendered value will only change if the value you provide changes. We can utilize useState for this purpose.

App.tsx
import { useState } from "react";

export default function App() {
const [value, setValue] = useState("Hi Fam!");

return (
<div>
<input
value={value}
onChange={(e) => {
setValue(e.target.value);
console.log(e.target.value);
}}
/>
</div>
);
}

Notice that the type of the event is inferred by TypeScript when the event handler is defined inline. In this case it is React.ChangeEvent<HTMLInputElement>.

Checkbox in React

A checkbox in html is simply an input with type="checkbox". And no surprise, this is exactly how you can create a checkbox in React.

You can also add a label to the checkbox and ensure they are linked by using the same value for input.id and label.htmlFor.

To control a checkbox you use the checked prop and wire it to a boolean.

App.tsx
App.module.css
import { useState } from 'react';
import styles from './App.module.css';

export default function App() {
const [checked, setChecked] = useState(false);
const toggle = () => setChecked(checked => !checked);

return (
<div className={styles.checkbox}>
<input
type='checkbox'
id='accept'
checked={checked}
onChange={toggle}
/>
<label htmlFor='accept'>
I accept the terms and conditions.
</label>
</div>
);
}
javascript
typescript
react
playwright

Enjoy free content straight from your inbox 💌

No spam, unsubscribe at any time.

Transcript

00:00

In this lesson, we will uncover event handling for dorm elements in React. We will start with the basics of handling simple clicks. We will follow this up by looking at controlled versus uncontrolled components. We will also uncover how to handle various input elements with different data types and the internal structure of reactants along with the touch script type definitions. So let's go to kick off with the basics. We create a simple button element and at this point, of course you can try and click it, but nothing will happen because we haven't attached any event handlers.

00:33

Now, creating an event handler within React is super simple. We simply define a function within the component and in order to listen to a particular event, we simply need to pass this function in as a prop for that event. Here we are saying that when the button gets clicked, we want the function on button click to get called. And indeed, when we interact with the button right now, we see the clicks getting logged to the console. Now for simple handlers like this, it is conventional to define them at the root of your component, but of course there's nothing stopping you from defining this as an expression within your JSX in terms of behavior.

01:08

This will be equivalent to the previous example, and this is most likely what you will do when working with loops. As a professional, it's a good idea to take a look at the TypeScript types for event handlers and events, and this will actually help uncover some of the internals of events in React. You can actually hover over the prop for on click to see what is the type that TypeScript expects here. It expects to be passed in React Mouse event handler for an HTML button element, so we can actually enforce that. Our function callback is going to follow this signature

01:41

by creating a variable of this particular type and assigning it a function event handler. Now, previously we were not taking in the event and if we were not going to use it right now, we could remove it as well. But let's log the event to the console and wire this particular event handler to our button. Now with this simple wiring in place, let's go ahead and interact with our button and we can see the event that gets logged to the console. Note that it is off type synthetic base event. Now React actually wraps the native event with this particular type for two key reasons.

02:14

First is performance, and the second is cross browser consistency. Note that we can still get access to the browser event by using the native event property of the synthetic event. So let's log out both of these to the console and interact with the button again. Now we have two objects logged to the console, the first containing the React event and the second containing the browser native event. Now if you look at the native event properties, a lot of these properties will actually also be present on the synthetic event that React provides us. This means that when working with React, you will most commonly only be working with the event object

02:49

and not its underlying native event. Now, the most common usage of event values that people have would be with input elements. So let's take a look at an example. Within Our ui, we create a basic input element and a neat way that we can use to provide the value for the input is by providing the proper default value. Now, there are actually two ways to manage form elements within React. One is controlled and the other is uncontrolled. Right now, this component is actually uncontrolled. What this means is that the value that it is showing is not being managed with any state variable.

03:23

So even though we say that it should start with the default value of High Fam, the user can actually interact with the input and set whatever value that they want. Now, we can actually subscribe to the change event for the input element by providing a function for the own change prop from the event that gets passed to this callback function, we can actually read target value, which is the value that the input element is going to try to show. Now the other form of form components is control components where the value of the component is always going to be what is set as the prop.

03:55

So if we set the value to be the string high fam, the component is always going to render the string high fam, even though the user can try to change the value. As we can see in the log statements coming from on change, what actually gets displayed is always that string high fam. Now, the proper way of course to use a component in a controlled fashion is to wire it to some state variable. Here we are initializing a state with the string high fam. We wire the value prop to that state value, and whenever the user tries to change it, we update the state with the new target value.

04:29

And with this simple change in place, if the user interacts with the input, the on change event gets fired, we get the new value that gets set in the state and the component renders with that new value. Let's talk a bit about some additional tricks that we can use when working with event handlers. Thanks to TypeScript, when you define the function callback in line in front of the prop, you can actually see what the inferred type is going to be for that event. In this particular case, it is going to be react change event for an HTML input element, and we can actually just copy this

05:02

and use it as a type declaration for the event. With this declaration in place, we can actually even select the entire function and then use a feature within VS code called quick fixes, which on a Mac you can invoke with commands dot, and then choose to extract the function as a constant in the enclosing scope. This lifts out the function with complete type safety and keeps our JS six from becoming messy. The input type that we have been working with works on top of a simple string, but there are other UI elements that work on top of other data structures. So let's take a look at another one in the

05:35

form of a checkbox. Now, to create a checkbox with an HDML, you actually still use an input tag. The only difference is that you provide that type as checkbox. Now, we are also using an ID prop over here and passing in the string except, and the reason for that will become obvious in a bit. But with this simple inputs tag, we do get an uncontrolled checkbox. Just like we previously saw an Uncontrolled text input. This means that the user can interact with it as much as they want and it is not being managed by any state. Now, with checkbox, it is conventional to add a label as well, and this is where that ID property becomes useful

06:09

because with the label we can see HTML four and provide the same string value, and the browser now automatically handles clicks on this particular label and wires them to that input element. Now, if you want a controlled checkbox, the property that we actually need to provide is called checked, and this takes a bullion. If you set it true, then the component is controlled and it's always going to stay true. If you say false, then the component is always going to stay false. So as an example, it is true, but hey, right now and when the user tries to click it,

06:41

even though the event gets fired, because it is controlled and set to true, it is always going to stay checked. Now, as we've learned before, if you want a control component, it is best to wire it to some state. Hey, we are creating a Boolean state, initializing it to false, and then creating a utility toggle function that basically inverts the value. If it is true, then it sets it to false. If it is false and it sets it true, and then we wire the checks property to this particular state value, and then for change event using the unchanged prop, we invoke the toggle function

07:14

and with this simple change in place, this particular control component behaves exactly how the user would expect they can click it again and again to toggle between unchecked and checked. I'll wrap things up there. As always, thank you for joining me and I will see you in the next one.