0
# Context and Utilities
1
2
Context providers for server-side rendering scenarios and utility functions for media query string generation and device property management.
3
4
## Capabilities
5
6
### React Context
7
8
React Context for providing device settings to all `useMediaQuery` hooks and `MediaQuery` components in the component tree. Essential for server-side rendering and testing scenarios.
9
10
```typescript { .api }
11
/**
12
* React Context for providing device settings globally
13
* Used for server-side rendering and testing with specific device characteristics
14
*/
15
const Context: React.Context<Partial<MediaQueryAllQueryable> | undefined>;
16
```
17
18
**Usage Examples:**
19
20
```typescript
21
import React from "react";
22
import { Context as ResponsiveContext, useMediaQuery, MediaQuery } from "react-responsive";
23
24
// Server-side rendering with device context
25
const SSRExample = () => {
26
// This would typically be set based on User-Agent headers
27
const deviceSettings = {
28
width: 768,
29
height: 1024,
30
orientation: "portrait" as const,
31
};
32
33
return (
34
<ResponsiveContext.Provider value={deviceSettings}>
35
<App />
36
</ResponsiveContext.Provider>
37
);
38
};
39
40
// Testing with specific device characteristics
41
const TestingExample = () => {
42
const mobileDevice = {
43
width: 375,
44
height: 667,
45
orientation: "portrait" as const,
46
};
47
48
const desktopDevice = {
49
width: 1920,
50
height: 1080,
51
orientation: "landscape" as const,
52
};
53
54
return (
55
<div>
56
<h2>Mobile Test</h2>
57
<ResponsiveContext.Provider value={mobileDevice}>
58
<ResponsiveComponent />
59
</ResponsiveContext.Provider>
60
61
<h2>Desktop Test</h2>
62
<ResponsiveContext.Provider value={desktopDevice}>
63
<ResponsiveComponent />
64
</ResponsiveContext.Provider>
65
</div>
66
);
67
};
68
69
// Component that uses the context
70
const ResponsiveComponent = () => {
71
const isMobile = useMediaQuery({ maxWidth: 767 });
72
const isDesktop = useMediaQuery({ minWidth: 1024 });
73
74
return (
75
<div>
76
<MediaQuery maxWidth={767}>
77
<p>Mobile view (from component)</p>
78
</MediaQuery>
79
{isMobile && <p>Mobile view (from hook)</p>}
80
{isDesktop && <p>Desktop view (from hook)</p>}
81
</div>
82
);
83
};
84
```
85
86
**Real-world SSR Example with Next.js:**
87
88
```typescript
89
// pages/_app.tsx
90
import { Context as ResponsiveContext } from "react-responsive";
91
import { GetServerSideProps } from "next";
92
93
interface AppProps {
94
deviceSettings?: {
95
width: number;
96
height: number;
97
orientation: "portrait" | "landscape";
98
};
99
}
100
101
const MyApp = ({ Component, pageProps, deviceSettings }: AppProps) => {
102
return (
103
<ResponsiveContext.Provider value={deviceSettings}>
104
<Component {...pageProps} />
105
</ResponsiveContext.Provider>
106
);
107
};
108
109
// Server-side device detection
110
export const getServerSideProps: GetServerSideProps = async ({ req }) => {
111
const userAgent = req.headers["user-agent"] || "";
112
113
// Simple device detection (in practice, use a proper library)
114
const isMobile = /Mobile|Android|iPhone|iPad/i.test(userAgent);
115
116
const deviceSettings = {
117
width: isMobile ? 375 : 1920,
118
height: isMobile ? 667 : 1080,
119
orientation: isMobile ? "portrait" as const : "landscape" as const,
120
};
121
122
return {
123
props: {
124
deviceSettings,
125
},
126
};
127
};
128
```
129
130
**Testing with React Testing Library:**
131
132
```typescript
133
import { render, screen } from "@testing-library/react";
134
import { Context as ResponsiveContext } from "react-responsive";
135
import MyResponsiveComponent from "./MyResponsiveComponent";
136
137
describe("MyResponsiveComponent", () => {
138
test("renders mobile layout", () => {
139
const mobileDevice = { width: 375, height: 667 };
140
141
render(
142
<ResponsiveContext.Provider value={mobileDevice}>
143
<MyResponsiveComponent />
144
</ResponsiveContext.Provider>
145
);
146
147
expect(screen.getByText("Mobile Layout")).toBeInTheDocument();
148
expect(screen.queryByText("Desktop Layout")).not.toBeInTheDocument();
149
});
150
151
test("renders desktop layout", () => {
152
const desktopDevice = { width: 1920, height: 1080 };
153
154
render(
155
<ResponsiveContext.Provider value={desktopDevice}>
156
<MyResponsiveComponent />
157
</ResponsiveContext.Provider>
158
);
159
160
expect(screen.getByText("Desktop Layout")).toBeInTheDocument();
161
expect(screen.queryByText("Mobile Layout")).not.toBeInTheDocument();
162
});
163
});
164
```
165
166
### toQuery Utility
167
168
Utility function that converts JavaScript object representation of media queries to CSS media query strings.
169
170
```typescript { .api }
171
/**
172
* Converts media query object to CSS media query string
173
* @param obj - Object with media query properties
174
* @returns CSS media query string
175
*/
176
function toQuery(obj: Partial<MediaQueryAllQueryable>): string;
177
```
178
179
**Usage Examples:**
180
181
```typescript
182
import { toQuery } from "react-responsive";
183
184
// Basic conversion
185
const queryString = toQuery({ minWidth: 768, maxWidth: 1024 });
186
console.log(queryString); // "(min-width: 768px) and (max-width: 1024px)"
187
188
// Complex query with multiple properties
189
const complexQuery = toQuery({
190
minWidth: 768,
191
orientation: "landscape",
192
color: true,
193
type: "screen"
194
});
195
console.log(complexQuery);
196
// "screen and (min-width: 768px) and (orientation: landscape) and color"
197
198
// Boolean properties
199
const printQuery = toQuery({
200
type: "print",
201
color: false, // Negated
202
monochrome: true
203
});
204
console.log(printQuery); // "print and not color and monochrome"
205
206
// Number conversion to px
207
const dimensionQuery = toQuery({
208
width: 1024,
209
height: 768,
210
minResolution: "2dppx"
211
});
212
console.log(dimensionQuery);
213
// "(width: 1024px) and (height: 768px) and (min-resolution: 2dppx)"
214
```
215
216
**Integration with Custom Logic:**
217
218
```typescript
219
import { toQuery, useMediaQuery } from "react-responsive";
220
221
const CustomMediaQueryHook = (breakpoints: Record<string, Partial<MediaQueryAllQueryable>>) => {
222
const results: Record<string, boolean> = {};
223
224
Object.entries(breakpoints).forEach(([name, query]) => {
225
const queryString = toQuery(query);
226
console.log(`${name} query:`, queryString);
227
228
// Use the generated query string with useMediaQuery
229
results[name] = useMediaQuery({ query: queryString });
230
});
231
232
return results;
233
};
234
235
// Usage
236
const ResponsiveComponent = () => {
237
const queries = CustomMediaQueryHook({
238
mobile: { maxWidth: 767 },
239
tablet: { minWidth: 768, maxWidth: 1023 },
240
desktop: { minWidth: 1024 },
241
portrait: { orientation: "portrait" },
242
retina: { minResolution: "2dppx" }
243
});
244
245
return (
246
<div>
247
{queries.mobile && <p>Mobile device</p>}
248
{queries.tablet && <p>Tablet device</p>}
249
{queries.desktop && <p>Desktop device</p>}
250
{queries.portrait && <p>Portrait orientation</p>}
251
{queries.retina && <p>High DPI display</p>}
252
</div>
253
);
254
};
255
```
256
257
### Media Query Object Properties
258
259
The utility functions and context work with the complete set of media query properties:
260
261
```typescript { .api }
262
interface MediaQueryAllQueryable extends MediaQueryFeatures, MediaQueryTypes {
263
// Dimension properties (support min/max variants)
264
width?: number | string;
265
height?: number | string;
266
deviceWidth?: number | string;
267
deviceHeight?: number | string;
268
269
// Aspect ratio properties (support min/max variants)
270
aspectRatio?: string;
271
deviceAspectRatio?: string;
272
273
// Display properties
274
color?: boolean;
275
colorIndex?: boolean;
276
monochrome?: boolean;
277
278
// Resolution properties (support min/max variants)
279
resolution?: number | string;
280
281
// Orientation and scan properties
282
orientation?: "portrait" | "landscape";
283
scan?: "progressive" | "interlace";
284
285
// Media type properties
286
type?: "all" | "grid" | "aural" | "braille" | "handheld" | "print" |
287
"projection" | "screen" | "tty" | "tv" | "embossed";
288
289
// All boolean media types
290
all?: boolean;
291
grid?: boolean;
292
aural?: boolean;
293
braille?: boolean;
294
handheld?: boolean;
295
print?: boolean;
296
projection?: boolean;
297
screen?: boolean;
298
tty?: boolean;
299
tv?: boolean;
300
embossed?: boolean;
301
302
// Min/max variants for all dimension properties
303
minWidth?: number | string;
304
maxWidth?: number | string;
305
minHeight?: number | string;
306
maxHeight?: number | string;
307
minDeviceWidth?: number | string;
308
maxDeviceWidth?: number | string;
309
minDeviceHeight?: number | string;
310
maxDeviceHeight?: number | string;
311
minAspectRatio?: string;
312
maxAspectRatio?: string;
313
minDeviceAspectRatio?: string;
314
maxDeviceAspectRatio?: string;
315
minColor?: number;
316
maxColor?: number;
317
minColorIndex?: number;
318
maxColorIndex?: number;
319
minMonochrome?: number;
320
maxMonochrome?: number;
321
minResolution?: number | string;
322
maxResolution?: number | string;
323
}
324
```
325
326
### Advanced Context Patterns
327
328
**Dynamic Context Updates:**
329
330
```typescript
331
import React, { createContext, useContext, useState, useEffect } from "react";
332
import { Context as ResponsiveContext } from "react-responsive";
333
334
// Custom context that updates based on actual window size
335
const DynamicResponsiveProvider = ({ children }: { children: React.ReactNode }) => {
336
const [deviceSettings, setDeviceSettings] = useState({
337
width: typeof window !== "undefined" ? window.innerWidth : 1024,
338
height: typeof window !== "undefined" ? window.innerHeight : 768,
339
});
340
341
useEffect(() => {
342
const handleResize = () => {
343
setDeviceSettings({
344
width: window.innerWidth,
345
height: window.innerHeight,
346
});
347
};
348
349
window.addEventListener("resize", handleResize);
350
return () => window.removeEventListener("resize", handleResize);
351
}, []);
352
353
return (
354
<ResponsiveContext.Provider value={deviceSettings}>
355
{children}
356
</ResponsiveContext.Provider>
357
);
358
};
359
```
360
361
## Type Definitions
362
363
```typescript { .api }
364
import { Context } from "react";
365
366
const Context: Context<Partial<MediaQueryAllQueryable> | undefined>;
367
368
function toQuery(obj: Partial<MediaQueryAllQueryable>): string;
369
370
interface MediaQueryAllQueryable {
371
// Complete interface with all media query properties
372
// (See full definition in index.md)
373
}
374
```