0
# Refs System
1
2
Reference system for accessing DOM nodes and component instances directly.
3
4
## Capabilities
5
6
### Create Ref
7
8
Creates ref objects for accessing DOM nodes and component instances.
9
10
```javascript { .api }
11
/**
12
* Create a ref object for accessing DOM nodes or component instances
13
* @returns {RefObject} Ref object with current property
14
*/
15
function createRef();
16
17
/**
18
* Ref object interface
19
*/
20
interface RefObject<T> {
21
/**
22
* Current reference value (DOM node or component instance)
23
*/
24
current: T | null;
25
}
26
```
27
28
**Usage Examples:**
29
30
```javascript
31
import { createRef, Component } from 'preact-compat';
32
33
class InputComponent extends Component {
34
constructor(props) {
35
super(props);
36
this.inputRef = createRef();
37
}
38
39
focusInput = () => {
40
if (this.inputRef.current) {
41
this.inputRef.current.focus();
42
}
43
};
44
45
componentDidMount() {
46
// Access DOM node directly
47
console.log(this.inputRef.current); // <input> element
48
}
49
50
render() {
51
return (
52
<div>
53
<input ref={this.inputRef} type="text" />
54
<button onClick={this.focusInput}>Focus Input</button>
55
</div>
56
);
57
}
58
}
59
```
60
61
### Callback Refs
62
63
Alternative ref pattern using callback functions.
64
65
```javascript { .api }
66
/**
67
* Callback ref function
68
* @param {Element|Component|null} instance - DOM node or component instance
69
*/
70
type RefCallback<T> = (instance: T | null) => void;
71
```
72
73
**Usage Examples:**
74
75
```javascript
76
import { Component } from 'preact-compat';
77
78
class CallbackRefComponent extends Component {
79
inputElement = null;
80
81
setInputRef = (element) => {
82
this.inputElement = element;
83
};
84
85
focusInput = () => {
86
if (this.inputElement) {
87
this.inputElement.focus();
88
}
89
};
90
91
render() {
92
return (
93
<div>
94
<input ref={this.setInputRef} type="text" />
95
<button onClick={this.focusInput}>Focus Input</button>
96
</div>
97
);
98
}
99
}
100
```
101
102
### Forwarding Refs
103
104
Pattern for passing refs through component boundaries.
105
106
```javascript
107
import { createRef, cloneElement } from 'preact-compat';
108
109
// Higher-order component that forwards refs
110
function withForwardedRef(WrappedComponent) {
111
return function ForwardedRefComponent(props) {
112
const { forwardedRef, ...otherProps } = props;
113
return <WrappedComponent ref={forwardedRef} {...otherProps} />;
114
};
115
}
116
117
// Usage
118
class MyInput extends Component {
119
focus() {
120
this.inputRef.current.focus();
121
}
122
123
render() {
124
return <input ref={this.inputRef} {...this.props} />;
125
}
126
}
127
128
const ForwardedInput = withForwardedRef(MyInput);
129
130
class ParentComponent extends Component {
131
constructor(props) {
132
super(props);
133
this.childRef = createRef();
134
}
135
136
handleClick = () => {
137
this.childRef.current.focus();
138
};
139
140
render() {
141
return (
142
<div>
143
<ForwardedInput forwardedRef={this.childRef} />
144
<button onClick={this.handleClick}>Focus Child</button>
145
</div>
146
);
147
}
148
}
149
```
150
151
### Refs with Functional Components
152
153
Using refs in functional components (note: hooks not available in preact-compat 3.19.0).
154
155
```javascript
156
import { createRef } from 'preact-compat';
157
158
// Ref passed as prop
159
function FunctionalInput({ inputRef, ...props }) {
160
return <input ref={inputRef} {...props} />;
161
}
162
163
// Usage
164
class ParentComponent extends Component {
165
constructor(props) {
166
super(props);
167
this.inputRef = createRef();
168
}
169
170
render() {
171
return (
172
<FunctionalInput
173
inputRef={this.inputRef}
174
placeholder="Type here..."
175
/>
176
);
177
}
178
}
179
```
180
181
### Common Ref Patterns
182
183
```javascript
184
import { createRef, Component } from 'preact-compat';
185
186
class RefPatternsExample extends Component {
187
constructor(props) {
188
super(props);
189
190
// Multiple refs
191
this.formRef = createRef();
192
this.inputRefs = {
193
username: createRef(),
194
password: createRef(),
195
email: createRef()
196
};
197
198
// Dynamic refs array
199
this.itemRefs = [];
200
}
201
202
// Create refs for dynamic list
203
setItemRef = (index) => (element) => {
204
this.itemRefs[index] = element;
205
};
206
207
// Scroll to specific item
208
scrollToItem = (index) => {
209
if (this.itemRefs[index]) {
210
this.itemRefs[index].scrollIntoView({ behavior: 'smooth' });
211
}
212
};
213
214
// Form submission
215
handleSubmit = (e) => {
216
e.preventDefault();
217
const form = this.formRef.current;
218
const formData = new FormData(form);
219
220
// Validate inputs
221
Object.values(this.inputRefs).forEach(ref => {
222
if (ref.current && !ref.current.value) {
223
ref.current.focus();
224
return;
225
}
226
});
227
};
228
229
render() {
230
const items = ['Item 1', 'Item 2', 'Item 3'];
231
232
return (
233
<div>
234
<form ref={this.formRef} onSubmit={this.handleSubmit}>
235
<input
236
ref={this.inputRefs.username}
237
name="username"
238
placeholder="Username"
239
/>
240
<input
241
ref={this.inputRefs.password}
242
name="password"
243
type="password"
244
placeholder="Password"
245
/>
246
<input
247
ref={this.inputRefs.email}
248
name="email"
249
type="email"
250
placeholder="Email"
251
/>
252
<button type="submit">Submit</button>
253
</form>
254
255
{items.map((item, index) => (
256
<div
257
key={index}
258
ref={this.setItemRef(index)}
259
onClick={() => this.scrollToItem(index)}
260
>
261
{item}
262
</div>
263
))}
264
</div>
265
);
266
}
267
}
268
```
269
270
## Types
271
272
```javascript { .api }
273
interface RefObject<T> {
274
current: T | null;
275
}
276
277
type RefCallback<T> = (instance: T | null) => void;
278
279
type Ref<T> = RefCallback<T> | RefObject<T>;
280
281
// Common ref types
282
type DOMRef = Ref<HTMLElement>;
283
type InputRef = Ref<HTMLInputElement>;
284
type FormRef = Ref<HTMLFormElement>;
285
type ComponentRef<T extends Component> = Ref<T>;
286
```