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

hooks.md docs/

1
# Hooks
2
3
React Hooks for state management, side effects, and component lifecycle in function components. Hooks allow you to use state and other React features without writing a class component.
4
5
## Capabilities
6
7
### useState
8
9
Hook for managing local component state in function components.
10
11
```typescript { .api }
12
/**
13
* Adds state to function components
14
* @param initialState - Initial state value or function returning initial state
15
* @returns Array with current state and state setter function
16
*/
17
function useState<S>(initialState: S | (() => S)): [S, React.Dispatch<React.SetStateAction<S>>];
18
19
type SetStateAction<S> = S | ((prevState: S) => S);
20
type Dispatch<A> = (value: A) => void;
21
```
22
23
**Usage Examples:**
24
25
```typescript
26
import React, { useState } from "react";
27
28
function Counter() {
29
const [count, setCount] = useState(0);
30
const [name, setName] = useState(() => "Initial Name");
31
32
return (
33
<div>
34
<p>Count: {count}</p>
35
<button onClick={() => setCount(count + 1)}>Increment</button>
36
<button onClick={() => setCount(prev => prev + 1)}>Increment (functional)</button>
37
38
<input
39
value={name}
40
onChange={e => setName(e.target.value)}
41
/>
42
</div>
43
);
44
}
45
```
46
47
### useEffect
48
49
Hook for performing side effects in function components (data fetching, subscriptions, DOM manipulation).
50
51
```typescript { .api }
52
/**
53
* Performs side effects in function components
54
* @param effect - Function containing side effect logic
55
* @param deps - Optional dependency array controlling when effect runs
56
*/
57
function useEffect(
58
effect: React.EffectCallback,
59
deps?: React.DependencyList
60
): void;
61
62
type EffectCallback = () => (void | (() => void | undefined));
63
type DependencyList = ReadonlyArray<any>;
64
```
65
66
**Usage Examples:**
67
68
```typescript
69
import React, { useState, useEffect } from "react";
70
71
function UserProfile({ userId }: { userId: string }) {
72
const [user, setUser] = useState(null);
73
const [loading, setLoading] = useState(true);
74
75
// Effect with cleanup
76
useEffect(() => {
77
let cancelled = false;
78
79
async function fetchUser() {
80
try {
81
const response = await fetch(`/api/users/${userId}`);
82
const userData = await response.json();
83
84
if (!cancelled) {
85
setUser(userData);
86
setLoading(false);
87
}
88
} catch (error) {
89
if (!cancelled) {
90
console.error("Failed to fetch user:", error);
91
setLoading(false);
92
}
93
}
94
}
95
96
fetchUser();
97
98
// Cleanup function
99
return () => {
100
cancelled = true;
101
};
102
}, [userId]); // Effect runs when userId changes
103
104
// Effect without dependencies (runs on every render)
105
useEffect(() => {
106
document.title = user ? `Profile: ${user.name}` : "Loading...";
107
});
108
109
if (loading) return <div>Loading...</div>;
110
return <div>User: {user?.name}</div>;
111
}
112
```
113
114
### useContext
115
116
Hook for consuming React context values.
117
118
```typescript { .api }
119
/**
120
* Consumes context value from the nearest Provider
121
* @param context - React context object created with createContext
122
* @returns Current context value
123
*/
124
function useContext<T>(context: React.Context<T>): T;
125
```
126
127
**Usage Examples:**
128
129
```typescript
130
import React, { useContext, createContext } from "react";
131
132
const ThemeContext = createContext<{ theme: string; toggleTheme: () => void }>({
133
theme: "light",
134
toggleTheme: () => {}
135
});
136
137
function ThemeButton() {
138
const { theme, toggleTheme } = useContext(ThemeContext);
139
140
return (
141
<button onClick={toggleTheme}>
142
Current theme: {theme}
143
</button>
144
);
145
}
146
```
147
148
### useReducer
149
150
Hook for state management using the reducer pattern, ideal for complex state logic.
151
152
```typescript { .api }
153
/**
154
* Manages state with a reducer function
155
* @param reducer - Function that takes current state and action, returns new state
156
* @param initialState - Initial state value
157
* @param initializer - Optional function to lazily initialize state
158
* @returns Array with current state and dispatch function
159
*/
160
function useReducer<R extends React.Reducer<any, any>>(
161
reducer: R,
162
initialState: React.ReducerState<R>,
163
initializer?: undefined
164
): [React.ReducerState<R>, React.Dispatch<React.ReducerAction<R>>];
165
166
function useReducer<R extends React.Reducer<any, any>, I>(
167
reducer: R,
168
initialArg: I,
169
initializer: (arg: I) => React.ReducerState<R>
170
): [React.ReducerState<R>, React.Dispatch<React.ReducerAction<R>>];
171
172
type Reducer<S, A> = (prevState: S, action: A) => S;
173
```
174
175
**Usage Examples:**
176
177
```typescript
178
import React, { useReducer } from "react";
179
180
interface State {
181
count: number;
182
error: string | null;
183
}
184
185
type Action =
186
| { type: "increment" }
187
| { type: "decrement" }
188
| { type: "reset" }
189
| { type: "error"; message: string };
190
191
function counterReducer(state: State, action: Action): State {
192
switch (action.type) {
193
case "increment":
194
return { ...state, count: state.count + 1, error: null };
195
case "decrement":
196
return { ...state, count: state.count - 1, error: null };
197
case "reset":
198
return { ...state, count: 0, error: null };
199
case "error":
200
return { ...state, error: action.message };
201
default:
202
return state;
203
}
204
}
205
206
function Counter() {
207
const [state, dispatch] = useReducer(counterReducer, { count: 0, error: null });
208
209
return (
210
<div>
211
<p>Count: {state.count}</p>
212
{state.error && <p>Error: {state.error}</p>}
213
<button onClick={() => dispatch({ type: "increment" })}>+</button>
214
<button onClick={() => dispatch({ type: "decrement" })}>-</button>
215
<button onClick={() => dispatch({ type: "reset" })}>Reset</button>
216
</div>
217
);
218
}
219
```
220
221
### useRef
222
223
Hook for creating mutable ref objects that persist across re-renders.
224
225
```typescript { .api }
226
/**
227
* Creates a mutable ref object
228
* @param initialValue - Initial value for the ref
229
* @returns Mutable ref object with current property
230
*/
231
function useRef<T = undefined>(): React.MutableRefObject<T | undefined>;
232
function useRef<T = undefined>(initialValue: T): React.MutableRefObject<T>;
233
function useRef<T>(initialValue: T | null): React.RefObject<T>;
234
235
interface MutableRefObject<T> {
236
current: T;
237
}
238
239
interface RefObject<T> {
240
readonly current: T | null;
241
}
242
```
243
244
**Usage Examples:**
245
246
```typescript
247
import React, { useRef, useEffect } from "react";
248
249
function TextInput() {
250
const inputRef = useRef<HTMLInputElement>(null);
251
const renderCount = useRef(0);
252
253
useEffect(() => {
254
renderCount.current += 1;
255
});
256
257
const focusInput = () => {
258
inputRef.current?.focus();
259
};
260
261
return (
262
<div>
263
<input ref={inputRef} type="text" />
264
<button onClick={focusInput}>Focus Input</button>
265
<p>Render count: {renderCount.current}</p>
266
</div>
267
);
268
}
269
```
270
271
### useLayoutEffect
272
273
Hook for synchronous side effects that run before the browser paints.
274
275
```typescript { .api }
276
/**
277
* Runs effect synchronously before browser paint
278
* @param effect - Function containing side effect logic
279
* @param deps - Optional dependency array controlling when effect runs
280
*/
281
function useLayoutEffect(
282
effect: React.EffectCallback,
283
deps?: React.DependencyList
284
): void;
285
```
286
287
**Usage Examples:**
288
289
```typescript
290
import React, { useLayoutEffect, useRef, useState } from "react";
291
292
function MeasureComponent() {
293
const divRef = useRef<HTMLDivElement>(null);
294
const [height, setHeight] = useState(0);
295
296
useLayoutEffect(() => {
297
if (divRef.current) {
298
setHeight(divRef.current.offsetHeight);
299
}
300
});
301
302
return (
303
<div>
304
<div ref={divRef} style={{ padding: "20px", border: "1px solid black" }}>
305
This div's height is {height}px
306
</div>
307
</div>
308
);
309
}
310
```
311
312
### useInsertionEffect
313
314
Hook designed for CSS-in-JS libraries to inject styles before layout effects run.
315
316
```typescript { .api }
317
/**
318
* Runs effect before all DOM mutations (for CSS-in-JS libraries)
319
* @param effect - Function containing side effect logic
320
* @param deps - Optional dependency array controlling when effect runs
321
*/
322
function useInsertionEffect(
323
effect: React.EffectCallback,
324
deps?: React.DependencyList
325
): void;
326
```
327
328
### useImperativeHandle
329
330
Hook for customizing the instance value exposed by a ref when using forwardRef.
331
332
```typescript { .api }
333
/**
334
* Customizes ref instance value exposed to parent components
335
* @param ref - Ref object from forwardRef
336
* @param createHandle - Function returning the handle object
337
* @param deps - Optional dependency array
338
*/
339
function useImperativeHandle<T, R extends T>(
340
ref: React.Ref<T> | undefined,
341
createHandle: () => R,
342
deps?: React.DependencyList
343
): void;
344
```
345
346
**Usage Examples:**
347
348
```typescript
349
import React, { useImperativeHandle, useRef, forwardRef } from "react";
350
351
interface InputHandle {
352
focus: () => void;
353
setValue: (value: string) => void;
354
}
355
356
const FancyInput = forwardRef<InputHandle, { placeholder?: string }>((props, ref) => {
357
const inputRef = useRef<HTMLInputElement>(null);
358
359
useImperativeHandle(ref, () => ({
360
focus: () => {
361
inputRef.current?.focus();
362
},
363
setValue: (value: string) => {
364
if (inputRef.current) {
365
inputRef.current.value = value;
366
}
367
}
368
}));
369
370
return <input ref={inputRef} placeholder={props.placeholder} />;
371
});
372
373
function Parent() {
374
const inputRef = useRef<InputHandle>(null);
375
376
return (
377
<div>
378
<FancyInput ref={inputRef} placeholder="Enter text" />
379
<button onClick={() => inputRef.current?.focus()}>Focus</button>
380
<button onClick={() => inputRef.current?.setValue("Hello!")}>Set Value</button>
381
</div>
382
);
383
}
384
```
385
386
### useDebugValue
387
388
Hook for displaying debug information in React DevTools for custom hooks.
389
390
```typescript { .api }
391
/**
392
* Displays debug value in React DevTools
393
* @param value - Value to display
394
* @param format - Optional formatter function
395
*/
396
function useDebugValue<T>(
397
value: T,
398
format?: (value: T) => any
399
): void;
400
```
401
402
**Usage Examples:**
403
404
```typescript
405
import React, { useState, useDebugValue } from "react";
406
407
function useCounter(initialValue: number = 0) {
408
const [count, setCount] = useState(initialValue);
409
410
// Shows "Counter: 5" in React DevTools
411
useDebugValue(count, count => `Counter: ${count}`);
412
413
const increment = () => setCount(c => c + 1);
414
const decrement = () => setCount(c => c - 1);
415
416
return { count, increment, decrement };
417
}
418
```
419
420
### useId
421
422
Hook for generating unique IDs that are consistent between server and client.
423
424
```typescript { .api }
425
/**
426
* Generates unique ID for accessibility attributes
427
* @returns Unique string ID
428
*/
429
function useId(): string;
430
```
431
432
**Usage Examples:**
433
434
```typescript
435
import React, { useId } from "react";
436
437
function PasswordField() {
438
const passwordHintId = useId();
439
440
return (
441
<div>
442
<label>
443
Password:
444
<input
445
type="password"
446
aria-describedby={passwordHintId}
447
/>
448
</label>
449
<div id={passwordHintId}>
450
Password should contain at least 8 characters
451
</div>
452
</div>
453
);
454
}
455
```
456
457
### useActionState
458
459
Hook for managing form actions and pending states.
460
461
```typescript { .api }
462
/**
463
* Manages form action state and pending status
464
* @param action - Action function to execute
465
* @param initialState - Initial state value
466
* @param permalink - Optional permalink for the action
467
* @returns Array with current state, action function, and pending status
468
*/
469
function useActionState<S, P>(
470
action: (state: S, payload: P) => S | Promise<S>,
471
initialState: S,
472
permalink?: string
473
): [state: S, formAction: (payload: P) => void, isPending: boolean];
474
```
475
476
**Usage Examples:**
477
478
```typescript
479
import React, { useActionState } from "react";
480
481
async function updateName(currentState: { name: string; error?: string }, formData: FormData) {
482
const name = formData.get("name") as string;
483
484
if (!name) {
485
return { name: currentState.name, error: "Name is required" };
486
}
487
488
// Simulate API call
489
await new Promise(resolve => setTimeout(resolve, 1000));
490
491
return { name, error: undefined };
492
}
493
494
function NameForm() {
495
const [state, formAction, isPending] = useActionState(updateName, { name: "" });
496
497
return (
498
<form action={formAction}>
499
<input
500
name="name"
501
defaultValue={state.name}
502
disabled={isPending}
503
/>
504
<button type="submit" disabled={isPending}>
505
{isPending ? "Updating..." : "Update"}
506
</button>
507
{state.error && <p style={{ color: "red" }}>{state.error}</p>}
508
</form>
509
);
510
}
511
```
512
513
### experimental_useEffectEvent
514
515
Experimental hook that creates event handlers that don't re-run effects when their dependencies change.
516
517
```typescript { .api }
518
/**
519
* Creates an event handler that can access current values without causing effect re-runs
520
* @param callback - The event handler function
521
* @returns A stable event handler function
522
*/
523
function experimental_useEffectEvent<Args extends any[], Return>(
524
callback: (...args: Args) => Return
525
): (...args: Args) => Return;
526
```
527
528
**Usage Examples:**
529
530
```typescript
531
import React, { useState, useEffect, experimental_useEffectEvent } from "react";
532
533
function Chat({ roomId }: { roomId: string }) {
534
const [message, setMessage] = useState("");
535
const [connection, setConnection] = useState<any>(null);
536
537
// Event handler that can access current state without re-subscribing
538
const onReceiveMessage = experimental_useEffectEvent((receivedMessage: string) => {
539
console.log("Received:", receivedMessage, "Current message:", message);
540
});
541
542
useEffect(() => {
543
const conn = createConnection(roomId);
544
conn.on("message", onReceiveMessage);
545
setConnection(conn);
546
conn.connect();
547
548
return () => {
549
conn.disconnect();
550
};
551
}, [roomId]); // Only re-run when roomId changes, not when message changes
552
553
return (
554
<div>
555
<input
556
value={message}
557
onChange={e => setMessage(e.target.value)}
558
placeholder="Type a message..."
559
/>
560
</div>
561
);
562
}
563
```
564
565
### useSyncExternalStore
566
567
Hook for subscribing to external data sources with support for server-side rendering and concurrent features.
568
569
```typescript { .api }
570
/**
571
* Subscribes to an external store and returns its current value
572
* @param subscribe - Function that subscribes to store changes
573
* @param getSnapshot - Function that returns the current store value
574
* @param getServerSnapshot - Optional function for server-side rendering
575
* @returns Current store value
576
*/
577
function useSyncExternalStore<Snapshot>(
578
subscribe: (onStoreChange: () => void) => () => void,
579
getSnapshot: () => Snapshot,
580
getServerSnapshot?: () => Snapshot
581
): Snapshot;
582
```
583
584
**Usage Examples:**
585
586
```typescript
587
import React, { useSyncExternalStore } from "react";
588
589
// Example: Browser online status store
590
const onlineStore = {
591
subscribe(callback: () => void) {
592
window.addEventListener("online", callback);
593
window.addEventListener("offline", callback);
594
return () => {
595
window.removeEventListener("online", callback);
596
window.removeEventListener("offline", callback);
597
};
598
},
599
getSnapshot() {
600
return navigator.onLine;
601
},
602
getServerSnapshot() {
603
return true; // Assume online on server
604
}
605
};
606
607
function OnlineStatus() {
608
const isOnline = useSyncExternalStore(
609
onlineStore.subscribe,
610
onlineStore.getSnapshot,
611
onlineStore.getServerSnapshot
612
);
613
614
return <div>Status: {isOnline ? "Online" : "Offline"}</div>;
615
}
616
617
// Example: Custom store
618
class CounterStore {
619
private count = 0;
620
private listeners = new Set<() => void>();
621
622
subscribe = (callback: () => void) => {
623
this.listeners.add(callback);
624
return () => this.listeners.delete(callback);
625
};
626
627
getSnapshot = () => this.count;
628
629
increment = () => {
630
this.count++;
631
this.listeners.forEach(callback => callback());
632
};
633
}
634
635
const counterStore = new CounterStore();
636
637
function Counter() {
638
const count = useSyncExternalStore(
639
counterStore.subscribe,
640
counterStore.getSnapshot
641
);
642
643
return (
644
<div>
645
<p>Count: {count}</p>
646
<button onClick={counterStore.increment}>Increment</button>
647
</div>
648
);
649
}
650
```
651
652
### use
653
654
Hook for consuming promises and context that can be used conditionally, unlike other hooks.
655
656
```typescript { .api }
657
/**
658
* Consumes a Promise or Context value
659
* @param usable - A Promise or React Context to consume
660
* @returns The resolved value of the Promise or the Context value
661
*/
662
function use<T>(usable: Promise<T>): T;
663
function use<T>(usable: React.Context<T>): T;
664
```
665
666
**Usage Examples:**
667
668
```typescript
669
import React, { use, createContext, Suspense } from "react";
670
671
// Example 1: Using with Context
672
const ThemeContext = createContext("light");
673
674
function Button() {
675
const theme = use(ThemeContext);
676
677
return (
678
<button className={`button-${theme}`}>
679
Themed Button
680
</button>
681
);
682
}
683
684
// Example 2: Using with Promises
685
async function fetchUser(id: string) {
686
const response = await fetch(`/api/users/${id}`);
687
return response.json();
688
}
689
690
function UserProfile({ userId }: { userId: string }) {
691
// This can be conditional, unlike other hooks
692
if (!userId) {
693
return <div>No user selected</div>;
694
}
695
696
const userPromise = fetchUser(userId);
697
const user = use(userPromise); // Suspends until promise resolves
698
699
return (
700
<div>
701
<h1>{user.name}</h1>
702
<p>{user.email}</p>
703
</div>
704
);
705
}
706
707
function App() {
708
const [userId, setUserId] = React.useState<string>("");
709
710
return (
711
<Suspense fallback={<div>Loading user...</div>}>
712
<input
713
value={userId}
714
onChange={e => setUserId(e.target.value)}
715
placeholder="Enter user ID"
716
/>
717
<UserProfile userId={userId} />
718
</Suspense>
719
);
720
}
721
```
722
723
## Types
724
725
### Hook-Related Types
726
727
```typescript { .api }
728
type EffectCallback = () => (void | (() => void | undefined));
729
type DependencyList = ReadonlyArray<any>;
730
731
type SetStateAction<S> = S | ((prevState: S) => S);
732
type Dispatch<A> = (value: A) => void;
733
734
type Reducer<S, A> = (prevState: S, action: A) => S;
735
type ReducerState<R extends Reducer<any, any>> = R extends Reducer<infer S, any> ? S : never;
736
type ReducerAction<R extends Reducer<any, any>> = R extends Reducer<any, infer A> ? A : never;
737
738
type MutableRefObject<T> = {
739
current: T;
740
};
741
742
type RefObject<T> = {
743
readonly current: T | null;
744
};
745
```