ReactHustle

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. 

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 (
    <div>
      <input
        onChange={(e) => {
          setInput(e.target.value);
        }}
      />
      {input}
    </div>
  );
}
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 (
    <div>
      <input onChange={handleChange} />
      {input}
    </div>
  );
}
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.

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

Technologies Used #

I assume you're using the following technologies.

  1. Typescript
  2. React
  3. VSCode editor

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 (
    <div>
      <input
        onChange={(e) => {
          setInput(e.target.value);
        }}
      />
      {input}
    </div>
  );
}
123456789101112131415

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 (
    <div>
      <input onChange={handleChange} />
      {input}
    </div>
  );
}
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.

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 (
    <div>
      <input onChange={handleChange} />
      {input}
    </div>
  );
}
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 (
    <div>
      {/* TypeError:  Types of parameters 'e' and 'event' are incompatible.
      Type 'ChangeEvent<HTMLInputElement>' is not assignable to type 'ChangeEvent<HTMLSelectElement>'.*/}
      <input onChange={handleChange} />
      {input}
    </div>
  );
}
12345678910111213141516

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 (
    <div>
      <input onChange={(e)=>{}} />
      {input}
    </div>
  );
}
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 (
    <div>
      <input onChange={handleChange} />
      {input}
    </div>
  );
}
1234567891011121314

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 (
    <div>
      <input
        onChange={(e: ChangeEvent<HTMLInputElement>) => {
          setInput(e.target.value);
        }}
      />
      {input}
    </div>
  );
}
12345678910111213141516

Now, you can easily refactor it to a named constant or use the refactoring feature of VScode.

Conclusion #

You learned how to declare the React onChange event handler manually and use tools to speed up coding while avoiding errors. The Typescript Explicit Types plugin is very useful in doing this.

If you like this tutorial, please leave a like or share this article. For future tutorials like this, please subscribe to our newsletter or follow me on GitHub.

Credits: Image by Veronika Andrews from Pixabay

Share this post!

Related Posts

Disclaimer

This content may contain links to products, software and services. Please assume all such links are affiliate links which may result in my earning commissions and fees.
As an Amazon Associate, I earn from qualifying purchases. This means that whenever you buy a product on Amazon from a link on our site, we receive a small percentage of its price at no extra cost to you. This helps us continue to provide valuable content and reviews to you. Thank you for your support!
Donate to ReactHustle