How to Create a React onChange Event Handler in Typescript
Jasser Mark Arioste
Hello! In this tutorial, you'll learn how to create React onChange event handlers in Typescript.
If you're a beginner in React, you might be having trouble creating a
onChange
or
onSubmit
event for basic HTML elements or sometimes in UI Components like MUI or Chakra UI.
For example, below we have an
onChange
event handler using an anonymous function:
import { useState } from "react"; export default function Component() { const [input, setInput] = useState(""); return ( <input onChange={(e) => { setInput(e.target.value); {input}
123456789101112131415
However, when you refactor and assign the
onChange
event handler to a constant. a type error occurs:
import { useState } from "react"; export default function Component() { const [input, setInput] = useState(""); const handleChange = (e) => { // Parameter 'e' implicitly has an 'any' type. setInput(e.target.value); return ( <input onChange={handleChange} /> {input}
1234567891011121314
In this tutorial, you'll learn a foolproof way to avoid type errors when creating onChange callback handlers by using the power of your editor.
- Learn how to create an onChange handler using an anonymous arrow function
- Learn how to create a separate onChange event handler defined through a constant
- Learn how to use the VSCode editor to create the callback function
- Using the Typescript Explicit Types plugin
I assume you're using the following technologies.
- Typescript
- React
- VSCode editor
This is the most basic, common, and fastest way to create event callbacks. But it's also the least readable and maintainable. Ideally, you avoid using this approach if possible. Another downside is that you won't be able to reuse the onChange event for other elements if needed.
import { useState } from "react"; export default function Component() { const [input, setInput] = useState(""); return ( <input onChange={(e) => { setInput(e.target.value); {input} }
123456789101112131415
Another way to define the
onChange
event is to use the
ChangeEventHandler
type. We can remove the type error in the first example by assigning a type to the
handleChange
function.
import { ChangeEventHandler, useState } from "react"; export default function Component() { const [input, setInput] = useState(""); const handleChange: ChangeEventHandler<HTMLInputElement> = (e) => { //no more errors setInput(e.target.value); return ( <input onChange={handleChange} /> {input}
1234567891011121314
Here we attach the type to the
handleChange
function. What this does is it automatically provides the type
ChangeEvent<HTMLInputElement>
to the
e
argument so it's no longer an
any
type.
When you hover over the
e
argument in your VSCode editor, it will have a type of
ChangeEvent<HTMLInputElement>
.
This approach is not commonly used compared to the next one.
Another way to declare the
onChange
event is to provide type to the
e
argument.
import { ChangeEvent, useState } from "react"; export default function Component() { const [input, setInput] = useState(""); const handleChange = (e: ChangeEvent<HTMLInputElement>) => { setInput(e.target.value); return ( <input onChange={handleChange} /> {input}
1234567891011121314
This approach is straightforward that you explicitly provide the type to the
e
argument.
If you provide the wrong type, it will result in a type error. For example:
import { ChangeEvent, useState } from "react"; export default function Component() { const [input, setInput] = useState(""); const handleChange = (e: ChangeEvent<HTMLSelectElement>) => { setInput(e.target.value); return ( {/* TypeError: Types of parameters 'e' and 'event' are incompatible. Type 'ChangeEvent<HTMLInputElement>' is not assignable to type 'ChangeEvent<HTMLSelectElement>'.*/} <input onChange={handleChange} /> {input}
12345678910111213141516
To determine the type of the
onChange
event handler or its
e
argument, you can use the type inference feature of VScode. First, define the onChange event using the anonymous arrow function method.
import { ChangeEvent, useState } from "react"; export default function Component() { const [input, setInput] = useState(""); return ( <input onChange={(e)=>{}} /> {input} }
123456789101112
Hover over the
e
argument. This will show
(parameter) e: ChangeEvent<HTMLInputElement>
Next, refactor and create a named constant event handler using the type from Step 2.
import { ChangeEvent, useState } from "react"; export default function Component() { const [input, setInput] = useState(""); const handleChange = (e: ChangeEvent<HTMLInputElement>) => { setInput(e.target.value); return ( <input onChange={handleChange} /> {input}
1234567891011121314
One very useful extension in VScode is the " Typescript Explicit Types " plugin. It provides a "Quick fix.." to automatically add the explicit type to whatever the type inference of a variable.
First, you set your cursor to the
e
argument. Then type
CTRL + .
or
CMD + .
to show the
"Quick fix..."
options. Below is a screenshot of how to use the plugin
After hitting the
ENTER
key, it would generate the code below:
import { ChangeEvent, useState } from "react";
export default function Component() {
const [input, setInput] = useState("");
return (
<input
onChange={(e: ChangeEvent<HTMLInputElement>) => {
setInput(e.target.value);