0
# Event Handling
1
2
Optimized event handling system with linkEvent for performance optimization and comprehensive synthetic event support for cross-browser compatibility.
3
4
## Capabilities
5
6
### Link Event
7
8
Performance-optimized event handling that links data to event handlers to avoid closure creation.
9
10
```typescript { .api }
11
/**
12
* Links data to event handlers for performance optimization
13
* @param data - Data to be passed as first argument to event handler
14
* @param event - Event handler function that receives data and event
15
* @returns LinkedEvent object or null if event is invalid
16
*/
17
function linkEvent<T, E extends Event>(
18
data: T,
19
event: (data: T, event: E) => void
20
): LinkedEvent<T, E> | null;
21
22
interface LinkedEvent<T, E extends Event> {
23
data: T;
24
event: (data: T, event: E) => void;
25
}
26
```
27
28
**Usage Examples:**
29
30
```typescript
31
import { linkEvent, createVNode, VNodeFlags } from "inferno";
32
33
class TodoList extends Component {
34
constructor(props) {
35
super(props);
36
this.state = { todos: [] };
37
}
38
39
// Event handler that receives data and event
40
handleRemoveTodo = (todoId, event) => {
41
this.setState(prevState => ({
42
todos: prevState.todos.filter(todo => todo.id !== todoId)
43
}));
44
};
45
46
render() {
47
return createVNode(VNodeFlags.HtmlElement, 'ul', null,
48
this.state.todos.map(todo =>
49
createVNode(VNodeFlags.HtmlElement, 'li', null, [
50
todo.text,
51
createVNode(VNodeFlags.HtmlElement, 'button', null, 'Remove', ChildFlags.HasInvalidChildren, {
52
// linkEvent passes todo.id as first argument to handler
53
onClick: linkEvent(todo.id, this.handleRemoveTodo)
54
})
55
])
56
)
57
);
58
}
59
}
60
61
// Alternative without linkEvent (less efficient)
62
class TodoListSlow extends Component {
63
handleRemoveTodo = (todoId) => (event) => {
64
// Creates new closure for each todo item
65
this.setState(prevState => ({
66
todos: prevState.todos.filter(todo => todo.id !== todoId)
67
}));
68
};
69
70
render() {
71
return createVNode(VNodeFlags.HtmlElement, 'ul', null,
72
this.state.todos.map(todo =>
73
createVNode(VNodeFlags.HtmlElement, 'li', null, [
74
todo.text,
75
createVNode(VNodeFlags.HtmlElement, 'button', null, 'Remove', ChildFlags.HasInvalidChildren, {
76
onClick: this.handleRemoveTodo(todo.id) // Creates closure
77
})
78
])
79
)
80
);
81
}
82
}
83
```
84
85
### Is Link Event Object
86
87
Utility function to check if an object is a linked event.
88
89
```typescript { .api }
90
/**
91
* Checks if an object is a linked event object
92
* @param o - Object to check
93
* @returns True if object is a LinkedEvent
94
*/
95
function isLinkEventObject(o: any): o is LinkedEvent<any, any>;
96
```
97
98
## Event Types
99
100
Comprehensive event handler types for all standard DOM events:
101
102
### Generic Event Handlers
103
104
```typescript { .api }
105
type EventHandler<E extends SemiSyntheticEvent<any>> =
106
| { bivarianceHack(event: E): void }['bivarianceHack']
107
| LinkedEvent<any, E>
108
| null;
109
110
type InfernoEventHandler<T = Element> = EventHandler<SemiSyntheticEvent<T>>;
111
```
112
113
### Specific Event Handlers
114
115
```typescript { .api }
116
type ClipboardEventHandler<T = Element> = EventHandler<ClipboardEvent<T>>;
117
type CompositionEventHandler<T = Element> = EventHandler<CompositionEvent<T>>;
118
type DragEventHandler<T = Element> = EventHandler<DragEvent<T>>;
119
type FocusEventHandler<T = Element> = EventHandler<FocusEvent<T>>;
120
type FormEventHandler<T = Element> = EventHandler<FormEvent<T>>;
121
type ChangeEventHandler<T = Element> = EventHandler<ChangeEvent<T>>;
122
type KeyboardEventHandler<T = Element> = EventHandler<InfernoKeyboardEvent<T>>;
123
type MouseEventHandler<T = Element> = EventHandler<InfernoMouseEvent<T>>;
124
type TouchEventHandler<T = Element> = EventHandler<InfernoTouchEvent<T>>;
125
type PointerEventHandler<T = Element> = EventHandler<InfernoPointerEvent<T>>;
126
type UIEventHandler<T = Element> = EventHandler<InfernoUIEvent<T>>;
127
type WheelEventHandler<T = Element> = EventHandler<InfernoWheelEvent<T>>;
128
type AnimationEventHandler<T = Element> = EventHandler<InfernoAnimationEvent<T>>;
129
type TransitionEventHandler<T = Element> = EventHandler<InfernoTransitionEvent<T>>;
130
```
131
132
## Synthetic Events
133
134
Inferno provides synthetic events for cross-browser compatibility:
135
136
### Base Synthetic Event
137
138
```typescript { .api }
139
interface SemiSyntheticEvent<T> extends Event {
140
/** A reference to the element on which the event listener is registered */
141
currentTarget: EventTarget & T;
142
isDefaultPrevented?: () => boolean;
143
isPropagationStopped?: () => boolean;
144
}
145
```
146
147
### Specific Event Types
148
149
```typescript { .api }
150
type ClipboardEvent<T> = SemiSyntheticEvent<T> & NativeClipboardEvent;
151
type CompositionEvent<T> = SemiSyntheticEvent<T> & NativeCompositionEvent;
152
type DragEvent<T> = InfernoMouseEvent<T> & NativeDragEvent;
153
type FocusEvent<T> = SemiSyntheticEvent<T> & NativeFocusEvent;
154
155
interface FormEvent<T> extends SemiSyntheticEvent<T> {
156
target: EventTarget & T;
157
}
158
159
interface ChangeEvent<T> extends SemiSyntheticEvent<T> {
160
target: EventTarget & T;
161
}
162
163
type InfernoKeyboardEvent<T> = SemiSyntheticEvent<T> & KeyboardEvent;
164
type InfernoMouseEvent<T> = SemiSyntheticEvent<T> & MouseEvent & {
165
target: EventTarget & T;
166
};
167
type InfernoTouchEvent<T> = SemiSyntheticEvent<T> & TouchEvent;
168
type InfernoPointerEvent<T> = SemiSyntheticEvent<T> & PointerEvent;
169
type InfernoUIEvent<T> = SemiSyntheticEvent<T> & UIEvent;
170
type InfernoWheelEvent<T> = InfernoMouseEvent<T> & WheelEvent;
171
type InfernoAnimationEvent<T> = SemiSyntheticEvent<T> & AnimationEvent;
172
type InfernoTransitionEvent<T> = SemiSyntheticEvent<T> & TransitionEvent;
173
```
174
175
## Event Usage Examples
176
177
### Mouse Events
178
179
```typescript
180
class ClickableComponent extends Component {
181
handleClick = (event: InfernoMouseEvent<HTMLButtonElement>) => {
182
console.log('Button clicked', event.currentTarget);
183
event.preventDefault();
184
};
185
186
handleMouseEnter = (message, event) => {
187
console.log(message, event.type);
188
};
189
190
render() {
191
return createVNode(VNodeFlags.HtmlElement, 'button', null, 'Click me', ChildFlags.HasInvalidChildren, {
192
onClick: this.handleClick,
193
onMouseEnter: linkEvent('Mouse entered!', this.handleMouseEnter)
194
});
195
}
196
}
197
```
198
199
### Form Events
200
201
```typescript
202
class FormComponent extends Component {
203
constructor(props) {
204
super(props);
205
this.state = { value: '' };
206
}
207
208
handleChange = (event: ChangeEvent<HTMLInputElement>) => {
209
this.setState({ value: event.target.value });
210
};
211
212
handleSubmit = (event: FormEvent<HTMLFormElement>) => {
213
event.preventDefault();
214
console.log('Submitted:', this.state.value);
215
};
216
217
render() {
218
return createVNode(VNodeFlags.HtmlElement, 'form', null, [
219
createVNode(VNodeFlags.InputElement, 'input', null, null, ChildFlags.HasInvalidChildren, {
220
type: 'text',
221
value: this.state.value,
222
onChange: this.handleChange
223
}),
224
createVNode(VNodeFlags.HtmlElement, 'button', null, 'Submit', ChildFlags.HasInvalidChildren, {
225
type: 'submit'
226
})
227
], ChildFlags.HasNonKeyedChildren, {
228
onSubmit: this.handleSubmit
229
});
230
}
231
}
232
```
233
234
### Keyboard Events
235
236
```typescript
237
class KeyboardComponent extends Component {
238
handleKeyDown = (event: InfernoKeyboardEvent<HTMLInputElement>) => {
239
if (event.key === 'Enter') {
240
console.log('Enter pressed');
241
} else if (event.key === 'Escape') {
242
console.log('Escape pressed');
243
}
244
};
245
246
render() {
247
return createVNode(VNodeFlags.InputElement, 'input', null, null, ChildFlags.HasInvalidChildren, {
248
onKeyDown: this.handleKeyDown,
249
placeholder: 'Press Enter or Escape'
250
});
251
}
252
}
253
```
254
255
## Performance Benefits of linkEvent
256
257
1. **No Closure Creation**: Avoids creating new functions for each render
258
2. **Memory Efficiency**: Reduces memory usage in lists with many items
259
3. **Consistent Performance**: Event handler creation cost is constant regardless of list size
260
4. **Garbage Collection**: Fewer objects created means less GC pressure
261
262
## Event Delegation
263
264
Inferno uses event delegation for improved performance:
265
266
- Events are attached to the document root instead of individual elements
267
- Single event listener handles all events of the same type
268
- Reduces memory usage and improves performance for large DOMs
269
- Automatically handles dynamically added/removed elements
270
271
## Cross-Browser Compatibility
272
273
Synthetic events provide consistent behavior across browsers:
274
275
- Normalized event properties and methods
276
- Consistent event bubbling and capturing
277
- Standardized preventDefault() and stopPropagation()
278
- Touch event support for mobile devices
279
- Pointer event support for modern browsers