Events are a fundamental part of any interactive web application, and TypeScript brings strong typing to React’s event handling system. This guide will show you how to handle events effectively in TypeScript React applications while maintaining type safety.
Table of Contents
- Understanding Event Types in TypeScript React
- Event Handler Best Practices
- Common Event Types Reference
- Advanced Event Handling Patterns
- Error Handling in Events
- Testing Event Handlers
Understanding Event Types in TypeScript React
TypeScript provides specific types for different DOM events in React applications. These types give you better type checking and autocompletion when handling user interactions.
Basic Event Types
Here are the most commonly used event types in TypeScript React:
type ButtonProps = {
onClick: (event: React.MouseEvent<HTMLButtonElement>) => void;
onHover: (event: React.MouseEvent<HTMLButtonElement>) => void;
}
const Button: React.FC<ButtonProps> = ({ onClick, onHover }) => {
return (
<button
onClick={onClick}
onMouseOver={onHover}
>
Click me
</button>
);
};
Code language: JavaScript (javascript)
Form Event Handling
Form events require special attention as they often involve user input:
type InputProps = {
onChange: (event: React.ChangeEvent<HTMLInputElement>) => void;
onSubmit: (event: React.FormEvent<HTMLFormElement>) => void;
}
const Form: React.FC<InputProps> = ({ onChange, onSubmit }) => {
return (
<form onSubmit={onSubmit}>
<input
type="text"
onChange={onChange}
placeholder="Type here"
/>
<button type="submit">Submit</button>
</form>
);
};
Code language: JavaScript (javascript)
Event Handler Best Practices
When working with event handlers in TypeScript React, follow these best practices:
1. Type Your Event Handlers Explicitly
const handleClick = (event: React.MouseEvent<HTMLButtonElement>): void => {
event.preventDefault();
console.log('Button clicked:', event.currentTarget.textContent);
};
Code language: JavaScript (javascript)
2. Use Event Type Inference
Let TypeScript infer the event types when possible:
const MyComponent: React.FC = () => {
const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
const value = event.target.value;
// TypeScript knows 'value' is a string
console.log(value.toUpperCase());
};
return <input onChange={handleChange} />;
};
Code language: JavaScript (javascript)
Common Event Types Reference
Here’s a comprehensive list of commonly used event types:
Mouse Events
type MouseEventProps = {
onClick: (event: React.MouseEvent<HTMLElement>) => void;
onMouseDown: (event: React.MouseEvent<HTMLElement>) => void;
onMouseUp: (event: React.MouseEvent<HTMLElement>) => void;
onMouseEnter: (event: React.MouseEvent<HTMLElement>) => void;
onMouseLeave: (event: React.MouseEvent<HTMLElement>) => void;
};
Code language: JavaScript (javascript)
Keyboard Events
type KeyboardEventProps = {
onKeyPress: (event: React.KeyboardEvent<HTMLElement>) => void;
onKeyDown: (event: React.KeyboardEvent<HTMLElement>) => void;
onKeyUp: (event: React.KeyboardEvent<HTMLElement>) => void;
};
Code language: JavaScript (javascript)
Advanced Event Handling Patterns
1. Generic Event Handlers
Create reusable event handlers that work with multiple element types:
function createEventHandler<T extends Element>(
handler: (event: React.MouseEvent<T>) => void
) {
return (event: React.MouseEvent<T>) => {
event.preventDefault();
handler(event);
};
}
const MyComponent: React.FC = () => {
const handleButtonClick = createEventHandler<HTMLButtonElement>((event) => {
console.log('Button clicked:', event.currentTarget.textContent);
});
return <button onClick={handleButtonClick}>Click Me</button>;
};
Code language: JavaScript (javascript)
2. Event Delegation
Handle multiple events efficiently using event delegation:
const ListComponent: React.FC = () => {
const handleItemClick = (event: React.MouseEvent<HTMLUListElement>) => {
const target = event.target as HTMLElement;
if (target.matches('li')) {
console.log('Clicked item:', target.textContent);
}
};
return (
<ul onClick={handleItemClick}>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
</ul>
);
};
Code language: JavaScript (javascript)
Error Handling in Events
Implement proper error handling in your event handlers:
const SafeButton: React.FC = () => {
const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {
try {
// Potentially risky operation
throw new Error('Something went wrong');
} catch (error) {
if (error instanceof Error) {
console.error('Error in click handler:', error.message);
}
// Prevent default behavior
event.preventDefault();
}
};
return <button onClick={handleClick}>Safe Button</button>;
};
Code language: JavaScript (javascript)
Testing Event Handlers
Write tests for your event handlers using React Testing Library:
import { render, fireEvent } from '@testing-library/react';
test('button click handler works correctly', () => {
const handleClick = jest.fn();
const { getByText } = render(
<button onClick={handleClick}>Test Button</button>
);
fireEvent.click(getByText('Test Button'));
expect(handleClick).toHaveBeenCalledTimes(1);
});
Code language: JavaScript (javascript)
By following these patterns and best practices, you’ll create type-safe, maintainable event handling code in your TypeScript React applications. Remember to always consider type safety and error handling when working with events, and take advantage of TypeScript’s powerful type system to catch potential issues at compile time rather than runtime.
For more advanced TypeScript topics, check out our guide on TypeScript Generics or explore TypeScript Union Types for additional type safety patterns.