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

context.md docs/

1
# Context API
2
3
React Context for sharing values between components without explicit prop passing. Context provides a way to pass data through the component tree without having to pass props down manually at every level.
4
5
## Capabilities
6
7
### createContext
8
9
Creates a React context object for sharing values across the component tree.
10
11
```typescript { .api }
12
/**
13
* Creates a new Context object
14
* @param defaultValue - Default value used when component has no matching Provider above it
15
* @returns Context object with Provider and Consumer components
16
*/
17
function createContext<T>(defaultValue: T): React.Context<T>;
18
19
interface Context<T> {
20
Provider: React.Provider<T>;
21
Consumer: React.Consumer<T>;
22
displayName?: string;
23
}
24
```
25
26
**Usage Examples:**
27
28
```typescript
29
import React, { createContext, useContext, useState } from "react";
30
31
// Create theme context with default value
32
interface ThemeContextType {
33
theme: "light" | "dark";
34
toggleTheme: () => void;
35
}
36
37
const ThemeContext = createContext<ThemeContextType>({
38
theme: "light",
39
toggleTheme: () => {}
40
});
41
42
// Provider component
43
function ThemeProvider({ children }: { children: React.ReactNode }) {
44
const [theme, setTheme] = useState<"light" | "dark">("light");
45
46
const toggleTheme = () => {
47
setTheme(prev => prev === "light" ? "dark" : "light");
48
};
49
50
return (
51
<ThemeContext.Provider value={{ theme, toggleTheme }}>
52
{children}
53
</ThemeContext.Provider>
54
);
55
}
56
57
// Consumer using useContext hook
58
function ThemedButton() {
59
const { theme, toggleTheme } = useContext(ThemeContext);
60
61
return (
62
<button
63
onClick={toggleTheme}
64
style={{
65
backgroundColor: theme === "light" ? "white" : "black",
66
color: theme === "light" ? "black" : "white"
67
}}
68
>
69
Toggle theme (current: {theme})
70
</button>
71
);
72
}
73
```
74
75
### Provider Component
76
77
Component that provides context values to its descendants.
78
79
```typescript { .api }
80
/**
81
* Provides context value to descendant components
82
*/
83
interface Provider<T> {
84
/**
85
* Value to provide to consumers
86
*/
87
value: T;
88
/**
89
* Child components that can consume the context
90
*/
91
children?: React.ReactNode;
92
}
93
```
94
95
**Usage Examples:**
96
97
```typescript
98
import React, { createContext, useState } from "react";
99
100
interface User {
101
id: string;
102
name: string;
103
email: string;
104
}
105
106
interface UserContextType {
107
user: User | null;
108
login: (user: User) => void;
109
logout: () => void;
110
}
111
112
const UserContext = createContext<UserContextType>({
113
user: null,
114
login: () => {},
115
logout: () => {}
116
});
117
118
function UserProvider({ children }: { children: React.ReactNode }) {
119
const [user, setUser] = useState<User | null>(null);
120
121
const login = (userData: User) => {
122
setUser(userData);
123
};
124
125
const logout = () => {
126
setUser(null);
127
};
128
129
return (
130
<UserContext.Provider value={{ user, login, logout }}>
131
{children}
132
</UserContext.Provider>
133
);
134
}
135
136
function App() {
137
return (
138
<UserProvider>
139
<Header />
140
<Main />
141
<Footer />
142
</UserProvider>
143
);
144
}
145
```
146
147
### Consumer Component
148
149
Legacy component for consuming context values (mostly replaced by useContext hook).
150
151
```typescript { .api }
152
/**
153
* Consumes context value using render prop pattern
154
*/
155
interface Consumer<T> {
156
children: (value: T) => React.ReactNode;
157
}
158
```
159
160
**Usage Examples:**
161
162
```typescript
163
import React, { createContext } from "react";
164
165
const ThemeContext = createContext("light");
166
167
function ThemedButton() {
168
return (
169
<ThemeContext.Consumer>
170
{theme => (
171
<button className={`button-${theme}`}>
172
Themed Button ({theme})
173
</button>
174
)}
175
</ThemeContext.Consumer>
176
);
177
}
178
179
// Preferred modern approach with useContext hook
180
function ModernThemedButton() {
181
const theme = useContext(ThemeContext);
182
183
return (
184
<button className={`button-${theme}`}>
185
Themed Button ({theme})
186
</button>
187
);
188
}
189
```
190
191
### useContext Hook
192
193
Hook for consuming context values (covered in detail in Hooks documentation).
194
195
```typescript { .api }
196
/**
197
* Consumes context value from the nearest Provider above
198
* @param context - React context object
199
* @returns Current context value
200
*/
201
function useContext<T>(context: React.Context<T>): T;
202
```
203
204
## Advanced Patterns
205
206
### Multiple Contexts
207
208
```typescript
209
import React, { createContext, useContext } from "react";
210
211
// User context
212
const UserContext = createContext<{ name: string } | null>(null);
213
214
// Settings context
215
const SettingsContext = createContext<{ language: string }>({
216
language: "en"
217
});
218
219
function UserProfile() {
220
const user = useContext(UserContext);
221
const settings = useContext(SettingsContext);
222
223
if (!user) {
224
return <div>Please log in</div>;
225
}
226
227
return (
228
<div>
229
<h1>Welcome, {user.name}!</h1>
230
<p>Language: {settings.language}</p>
231
</div>
232
);
233
}
234
235
function App() {
236
return (
237
<UserContext.Provider value={{ name: "Alice" }}>
238
<SettingsContext.Provider value={{ language: "es" }}>
239
<UserProfile />
240
</SettingsContext.Provider>
241
</UserContext.Provider>
242
);
243
}
244
```
245
246
### Context with Reducer
247
248
```typescript
249
import React, { createContext, useContext, useReducer } from "react";
250
251
interface State {
252
count: number;
253
user: { name: string } | null;
254
}
255
256
type Action =
257
| { type: "increment" }
258
| { type: "decrement" }
259
| { type: "setUser"; user: { name: string } }
260
| { type: "logout" };
261
262
function appReducer(state: State, action: Action): State {
263
switch (action.type) {
264
case "increment":
265
return { ...state, count: state.count + 1 };
266
case "decrement":
267
return { ...state, count: state.count - 1 };
268
case "setUser":
269
return { ...state, user: action.user };
270
case "logout":
271
return { ...state, user: null };
272
default:
273
return state;
274
}
275
}
276
277
interface AppContextType {
278
state: State;
279
dispatch: React.Dispatch<Action>;
280
}
281
282
const AppContext = createContext<AppContextType | null>(null);
283
284
function AppProvider({ children }: { children: React.ReactNode }) {
285
const [state, dispatch] = useReducer(appReducer, {
286
count: 0,
287
user: null
288
});
289
290
return (
291
<AppContext.Provider value={{ state, dispatch }}>
292
{children}
293
</AppContext.Provider>
294
);
295
}
296
297
function useAppContext() {
298
const context = useContext(AppContext);
299
if (!context) {
300
throw new Error("useAppContext must be used within AppProvider");
301
}
302
return context;
303
}
304
305
function Counter() {
306
const { state, dispatch } = useAppContext();
307
308
return (
309
<div>
310
<p>Count: {state.count}</p>
311
<button onClick={() => dispatch({ type: "increment" })}>+</button>
312
<button onClick={() => dispatch({ type: "decrement" })}>-</button>
313
</div>
314
);
315
}
316
```
317
318
### Avoiding Context Performance Issues
319
320
```typescript
321
import React, { createContext, useContext, useMemo, useState } from "react";
322
323
// Separate contexts for values and actions to prevent unnecessary re-renders
324
const StateContext = createContext<{ count: number; user: string | null }>(null!);
325
const ActionsContext = createContext<{
326
increment: () => void;
327
setUser: (user: string) => void;
328
}>(null!);
329
330
function AppProvider({ children }: { children: React.ReactNode }) {
331
const [count, setCount] = useState(0);
332
const [user, setUser] = useState<string | null>(null);
333
334
// Memoize actions to prevent re-creation on every render
335
const actions = useMemo(() => ({
336
increment: () => setCount(c => c + 1),
337
setUser: (newUser: string) => setUser(newUser)
338
}), []);
339
340
// Memoize state to prevent unnecessary re-renders
341
const state = useMemo(() => ({ count, user }), [count, user]);
342
343
return (
344
<StateContext.Provider value={state}>
345
<ActionsContext.Provider value={actions}>
346
{children}
347
</ActionsContext.Provider>
348
</StateContext.Provider>
349
);
350
}
351
352
function useAppState() {
353
return useContext(StateContext);
354
}
355
356
function useAppActions() {
357
return useContext(ActionsContext);
358
}
359
```
360
361
## Types
362
363
### Context-Related Types
364
365
```typescript { .api }
366
interface Context<T> {
367
Provider: Provider<T>;
368
Consumer: Consumer<T>;
369
displayName?: string;
370
}
371
372
interface Provider<T> {
373
value: T;
374
children?: ReactNode;
375
}
376
377
interface Consumer<T> {
378
children: (value: T) => ReactNode;
379
}
380
381
type ContextType<C extends Context<any>> = C extends Context<infer T> ? T : never;
382
```