In Preact, event handling follows a pattern similar to React, utilizing a synthetic event system to provide a consistent interface across browsers.
Event Binding
In Preact, event handlers are bound to elements via JSX, using camelCase event names.
Class Component Event Binding
import { Component } from 'preact';
class MyComponent extends Component {
handleClick = () => {
console.log('Button clicked!');
};
render() {
return (
<button onClick={this.handleClick}>
Click me!
</button>
);
}
}Function Component Event Binding
Use useRef to maintain function references in function components, avoiding new function instances on each render.
import { useRef, useState } from 'preact/hooks';
function MyComponent() {
const [count, setCount] = useState(0);
const handleClick = useRef(() => {
setCount(count + 1);
}).current;
return (
<button onClick={handleClick}>
Clicked {count} times
</button>
);
}Common Event Types
Preact supports various event types, including mouse, keyboard, and form events.
Mouse Events
Common mouse events include:
onClickonDoubleClickonMouseEnteronMouseLeaveonMouseMoveonMouseDownonMouseUp
Example:
import { h, Component } from 'preact';
class MouseEvents extends Component {
handleMouseEnter = () => {
console.log('Mouse entered');
};
handleMouseLeave = () => {
console.log('Mouse left');
};
render() {
return (
<div
onMouseEnter={this.handleMouseEnter}
onMouseLeave={this.handleMouseLeave}
style={{ width: '200px', height: '200px', backgroundColor: 'lightblue' }}
>
Hover over me
</div>
);
}
}
export default MouseEvents;Keyboard Events
Common keyboard events include:
onKeyDownonKeyUponKeyPress
Example:
import { h, Component } from 'preact';
class KeyEvents extends Component {
handleKeyDown = (event) => {
console.log(`Key pressed: ${event.key}`);
};
render() {
return <input type="text" onKeyDown={this.handleKeyDown} />;
}
}
export default KeyEvents;Form Events
Common form events include:
onChangeonInputonSubmit
Example:
import { h, Component } from 'preact';
class FormEvents extends Component {
handleChange = (event) => {
console.log(`Input changed: ${event.target.value}`);
};
handleSubmit = (event) => {
event.preventDefault();
console.log('Form submitted');
};
render() {
return (
<form onSubmit={this.handleSubmit}>
<input type="text" onChange={this.handleChange} />
<button type="submit">Submit</button>
</form>
);
}
}
export default FormEvents;Other Events
Other common events include:
onFocusonBluronResizeonScroll
Example:
import { h, Component } from 'preact';
class FocusBlurEvents extends Component {
handleFocus = () => {
console.log('Input focused');
};
handleBlur = () => {
console.log('Input blurred');
};
render() {
return <input type="text" onFocus={this.handleFocus} onBlur={this.handleBlur} />;
}
}
export default FocusBlurEvents;Event Handling Techniques
Passing Parameters
To pass additional parameters to event handlers, use arrow functions or the bind method.
import { h, Component } from 'preact';
class ParameterPassing extends Component {
handleClick = (id, event) => {
console.log(`Button ${id} clicked`);
};
render() {
return (
<button onClick={(event) => this.handleClick(1, event)}>Click me</button>
);
}
}
export default ParameterPassing;Using this
In class components, ensure event handlers are bound to the correct this context using arrow functions or binding in the constructor.
import { h, Component } from 'preact';
class ThisBinding extends Component {
constructor(props) {
super(props);
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
console.log('Button clicked', this);
}
render() {
return <button onClick={this.handleClick}>Click me</button>;
}
}
export default ThisBinding;Event Object
Preact’s event object is similar to the native DOM event object but encapsulated for compatibility and performance.
Accessing the Event Object
handleClick = (event) => {
console.log(event.target); // Access the element that triggered the event
};Event Delegation
Event delegation optimizes event handling by attaching a single listener to a parent element instead of individual listeners on each child.
Using Event Delegation
<div id="list">
{/* List of child elements */}
</div>
handleClick = (event) => {
if (event.target.tagName === 'BUTTON') {
console.log('Button clicked!');
}
};
render() {
return (
<div id="list" onClick={this.handleClick}>
{/* List of child elements */}
</div>
);
}Preventing Event Bubbling and Default Behavior
- Prevent Bubbling: Use
event.stopPropagation(). - Prevent Default Behavior: Use
event.preventDefault().
handleClick = (event) => {
event.stopPropagation();
event.preventDefault();
};Removing Event Listeners
While Preact manages most event listeners automatically, you may need to manually remove them in certain cases.
Removing Listeners on Component Unmount
componentWillUnmount() {
window.removeEventListener('scroll', this.handleScroll);
}Using Custom Events
Preact supports custom events for passing complex data between components.
Dispatching Custom Events
fireCustomEvent = () => {
this.dispatchEvent(new CustomEvent('myEvent', { detail: { message: 'Hello' } }));
};Listening for Custom Events
componentDidMount() {
this.addEventListener('myEvent', this.handleMyEvent);
}
handleMyEvent = (event) => {
console.log(event.detail.message);
};Handling Events with Hooks
Hooks simplify event and state handling in function components.
import { h } from 'preact';
import { useState } from 'preact/hooks';
const Counter = () => {
const [count, setCount] = useState(0);
const handleClick = () => {
setCount(count + 1);
};
return (
<div>
<p>Count: {count}</p>
<button onClick={handleClick}>Increment</button>
</div>
);
};
export default Counter;



