npm-react

Description
React is a JavaScript library for building user interfaces with a declarative, component-based approach.
Author
tessl
Last updated

How to use

npx @tessl/cli registry install tessl/npm-react@19.1.0

refs.md docs/

1
# Refs and Forward Refs
2
3
Reference system for accessing DOM nodes and component instances. Refs provide a way to access DOM nodes or React elements created in the render method directly.
4
5
## Capabilities
6
7
### createRef
8
9
Creates a ref object for accessing DOM nodes in class components.
10
11
```typescript { .api }
12
/**
13
* Creates a ref object for class components
14
* @returns RefObject with current property
15
*/
16
function createRef<T = any>(): React.RefObject<T>;
17
18
interface RefObject<T> {
19
readonly current: T | null;
20
}
21
```
22
23
**Usage Examples:**
24
25
```typescript
26
import React, { Component, createRef } from "react";
27
28
class TextInput extends Component {
29
private inputRef = createRef<HTMLInputElement>();
30
31
focusInput = () => {
32
this.inputRef.current?.focus();
33
};
34
35
render() {
36
return (
37
<div>
38
<input ref={this.inputRef} type="text" />
39
<button onClick={this.focusInput}>Focus Input</button>
40
</div>
41
);
42
}
43
}
44
```
45
46
### useRef Hook
47
48
Hook for creating mutable ref objects in function components (covered in detail in Hooks documentation).
49
50
```typescript { .api }
51
/**
52
* Creates a mutable ref object for function components
53
* @param initialValue - Initial value for the ref
54
* @returns MutableRefObject with current property
55
*/
56
function useRef<T = undefined>(): React.MutableRefObject<T | undefined>;
57
function useRef<T = undefined>(initialValue: T): React.MutableRefObject<T>;
58
function useRef<T>(initialValue: T | null): React.RefObject<T>;
59
60
interface MutableRefObject<T> {
61
current: T;
62
}
63
```
64
65
**Usage Examples:**
66
67
```typescript
68
import React, { useRef, useEffect } from "react";
69
70
function AutoFocusInput() {
71
const inputRef = useRef<HTMLInputElement>(null);
72
const renderCount = useRef(0);
73
74
useEffect(() => {
75
inputRef.current?.focus();
76
renderCount.current += 1;
77
});
78
79
return (
80
<div>
81
<input ref={inputRef} type="text" />
82
<p>Component rendered {renderCount.current} times</p>
83
</div>
84
);
85
}
86
```
87
88
### forwardRef
89
90
Higher-order component that forwards refs to child components.
91
92
```typescript { .api }
93
/**
94
* Forwards refs through components to child elements
95
* @param render - Render function that receives props and ref
96
* @returns Component that forwards refs
97
*/
98
function forwardRef<T, P = {}>(
99
render: (props: P, ref: React.Ref<T>) => React.ReactElement | null
100
): React.ForwardRefExoticComponent<React.PropsWithoutRef<P> & React.RefAttributes<T>>;
101
102
type Ref<T> = RefCallback<T> | RefObject<T> | null;
103
type RefCallback<T> = (instance: T | null) => void;
104
```
105
106
**Usage Examples:**
107
108
```typescript
109
import React, { forwardRef, useRef } from "react";
110
111
interface InputProps {
112
label?: string;
113
placeholder?: string;
114
}
115
116
// Forward ref to the actual input element
117
const FancyInput = forwardRef<HTMLInputElement, InputProps>((props, ref) => {
118
return (
119
<div className="fancy-input">
120
{props.label && <label>{props.label}</label>}
121
<input
122
ref={ref}
123
placeholder={props.placeholder}
124
className="fancy-input-field"
125
/>
126
</div>
127
);
128
});
129
130
function App() {
131
const inputRef = useRef<HTMLInputElement>(null);
132
133
const focusInput = () => {
134
inputRef.current?.focus();
135
};
136
137
return (
138
<div>
139
<FancyInput
140
ref={inputRef}
141
label="Name"
142
placeholder="Enter your name"
143
/>
144
<button onClick={focusInput}>Focus Input</button>
145
</div>
146
);
147
}
148
```
149
150
### useImperativeHandle
151
152
Hook for customizing the instance value exposed by a ref when using forwardRef (covered in detail in Hooks documentation).
153
154
```typescript { .api }
155
/**
156
* Customizes the instance value exposed to parent components when using forwardRef
157
* @param ref - The ref object
158
* @param createHandle - Function that returns the handle
159
* @param deps - Optional dependency array
160
*/
161
function useImperativeHandle<T, R extends T>(
162
ref: React.Ref<T> | undefined,
163
createHandle: () => R,
164
deps?: React.DependencyList
165
): void;
166
```
167
168
**Usage Examples:**
169
170
```typescript
171
import React, { forwardRef, useImperativeHandle, useRef, useImperativeHandle } from "react";
172
173
interface VideoPlayerHandle {
174
play: () => void;
175
pause: () => void;
176
getCurrentTime: () => number;
177
}
178
179
interface VideoPlayerProps {
180
src: string;
181
}
182
183
const VideoPlayer = forwardRef<VideoPlayerHandle, VideoPlayerProps>((props, ref) => {
184
const videoRef = useRef<HTMLVideoElement>(null);
185
186
useImperativeHandle(ref, () => ({
187
play: () => {
188
videoRef.current?.play();
189
},
190
pause: () => {
191
videoRef.current?.pause();
192
},
193
getCurrentTime: () => {
194
return videoRef.current?.currentTime ?? 0;
195
}
196
}));
197
198
return <video ref={videoRef} src={props.src} />;
199
});
200
201
function VideoApp() {
202
const playerRef = useRef<VideoPlayerHandle>(null);
203
204
const handlePlay = () => {
205
playerRef.current?.play();
206
};
207
208
const handlePause = () => {
209
playerRef.current?.pause();
210
};
211
212
const showCurrentTime = () => {
213
const time = playerRef.current?.getCurrentTime();
214
alert(`Current time: ${time}s`);
215
};
216
217
return (
218
<div>
219
<VideoPlayer ref={playerRef} src="/video.mp4" />
220
<button onClick={handlePlay}>Play</button>
221
<button onClick={handlePause}>Pause</button>
222
<button onClick={showCurrentTime}>Show Time</button>
223
</div>
224
);
225
}
226
```
227
228
## Ref Patterns
229
230
### Callback Refs
231
232
```typescript
233
import React, { useState, useCallback } from "react";
234
235
function CallbackRefExample() {
236
const [height, setHeight] = useState(0);
237
238
const measuredRef = useCallback((node: HTMLDivElement | null) => {
239
if (node !== null) {
240
setHeight(node.getBoundingClientRect().height);
241
}
242
}, []);
243
244
return (
245
<div>
246
<div ref={measuredRef}>
247
This div's height is {height}px
248
</div>
249
</div>
250
);
251
}
252
```
253
254
### Ref Array Pattern
255
256
```typescript
257
import React, { useRef, useEffect } from "react";
258
259
function ListWithRefs() {
260
const itemRefs = useRef<(HTMLLIElement | null)[]>([]);
261
const items = ["Item 1", "Item 2", "Item 3"];
262
263
useEffect(() => {
264
// Focus the second item
265
itemRefs.current[1]?.focus();
266
}, []);
267
268
return (
269
<ul>
270
{items.map((item, index) => (
271
<li
272
key={item}
273
ref={(el) => itemRefs.current[index] = el}
274
tabIndex={0}
275
>
276
{item}
277
</li>
278
))}
279
</ul>
280
);
281
}
282
```
283
284
### Conditional Refs
285
286
```typescript
287
import React, { useRef, useState } from "react";
288
289
function ConditionalRefExample() {
290
const [showInput, setShowInput] = useState(false);
291
const inputRef = useRef<HTMLInputElement>(null);
292
293
const handleToggle = () => {
294
setShowInput(!showInput);
295
296
// Focus input when it becomes available
297
setTimeout(() => {
298
inputRef.current?.focus();
299
}, 0);
300
};
301
302
return (
303
<div>
304
<button onClick={handleToggle}>
305
{showInput ? "Hide" : "Show"} Input
306
</button>
307
{showInput && (
308
<input
309
ref={inputRef}
310
type="text"
311
placeholder="I will be focused"
312
/>
313
)}
314
</div>
315
);
316
}
317
```
318
319
### Ref with Custom Hook
320
321
```typescript
322
import React, { useRef, useLayoutEffect, useState } from "react";
323
324
function useElementSize<T extends HTMLElement = HTMLDivElement>() {
325
const ref = useRef<T>(null);
326
const [size, setSize] = useState({ width: 0, height: 0 });
327
328
useLayoutEffect(() => {
329
const element = ref.current;
330
if (!element) return;
331
332
const updateSize = () => {
333
const rect = element.getBoundingClientRect();
334
setSize({ width: rect.width, height: rect.height });
335
};
336
337
updateSize();
338
339
const resizeObserver = new ResizeObserver(updateSize);
340
resizeObserver.observe(element);
341
342
return () => resizeObserver.disconnect();
343
}, []);
344
345
return { ref, size };
346
}
347
348
function ResizableDiv() {
349
const { ref, size } = useElementSize<HTMLDivElement>();
350
351
return (
352
<div
353
ref={ref}
354
style={{
355
width: "50%",
356
height: "200px",
357
backgroundColor: "lightblue",
358
resize: "both",
359
overflow: "auto"
360
}}
361
>
362
Size: {size.width} × {size.height}
363
</div>
364
);
365
}
366
```
367
368
## Types
369
370
### Ref-Related Types
371
372
```typescript { .api }
373
type Ref<T> = RefCallback<T> | RefObject<T> | null;
374
375
type RefCallback<T> = (instance: T | null) => void;
376
377
interface RefObject<T> {
378
readonly current: T | null;
379
}
380
381
interface MutableRefObject<T> {
382
current: T;
383
}
384
385
interface RefAttributes<T> {
386
ref?: Ref<T>;
387
}
388
389
interface ClassAttributes<T> extends Attributes {
390
ref?: Ref<T>;
391
}
392
393
type ForwardRefExoticComponent<P> = NamedExoticComponent<P> & {
394
render: (props: P, ref: any) => ReactElement | null;
395
};
396
397
type PropsWithoutRef<P> = P extends any ? ('ref' extends keyof P ? Pick<P, Exclude<keyof P, 'ref'>> : P) : P;
398
399
type PropsWithRef<P> = P extends any ? P & { ref?: Ref<any> } : P;
400
```