Sponsored

How to Create a React onChange Event Handler in Typescript

Jasser Mark Arioste

Jasser Mark Arioste

How to Create a React onChange Event Handler in Typescript

Hello! In this tutorial, you'll learn how to create React onChange event handlers in Typescript.

Sponsored

Introduction #

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.

Sponsored

Tutorial Objectives #

  1. Learn how to create an onChange handler using an anonymous arrow function
  2. Learn how to create a separate onChange event handler defined through a constant
  3. Learn how to use the VSCode editor to create the callback function
  4. Using the Typescript Explicit Types plugin
Sponsored

Technologies Used #

I assume you're using the following technologies.

  1. Typescript
  2. React
  3. VSCode editor
Sponsored

Defining onChange event using an arrow function #

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
Sponsored

Using ChangeEventHandler<HTMLInputElement> #

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> .

React ChangeEventHandler typescript

This approach is not commonly used compared to the next one.

Sponsored

Using ChangeEvent<HTMLInputElement> #

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
Sponsored

Using Type Inference to Determine the Type #

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>

React Change Event Typescript Anonymous Arrow Function

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
Sponsored

Using the Typescript Explicit Types Plugin #

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

Typescript Explicit Type Plugin on e argument of onChange event

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);