0
# Component Context
1
2
React Context system for providing Material UI components to form elements, enabling version compatibility and dependency injection. The context system allows widgets and fields to access Material UI components without direct imports.
3
4
## Capabilities
5
6
### MuiComponentContext
7
8
React Context that provides Material UI components to all child widgets and fields.
9
10
```typescript { .api }
11
/**
12
* React Context for providing Material UI components to widgets and fields
13
* Can hold either Material UI v4 or v5 component references
14
*/
15
declare const MuiComponentContext: React.Context<MaterialUIContextProps | Mui5ContextProps | null>;
16
```
17
18
**Features:**
19
- Version-agnostic component access
20
- Dependency injection for Material UI components
21
- Null-safe context handling
22
- Support for both v4 and v5 simultaneously
23
24
**Usage:**
25
- Automatically provided by form wrappers
26
- Accessed via useMuiComponent hook
27
- Can be customized for testing or specialized use cases
28
29
### useMuiComponent Hook
30
31
Hook for accessing Material UI components from the context within widgets and fields.
32
33
```typescript { .api }
34
/**
35
* Hook to access Material UI components from context
36
* @returns MaterialUIContextProps | Mui5ContextProps
37
* @throws Error if no context provider is found
38
*/
39
function useMuiComponent(): MaterialUIContextProps | Mui5ContextProps;
40
```
41
42
**Features:**
43
- Type-safe component access
44
- Runtime error checking
45
- Version detection
46
- Component availability validation
47
48
**Usage:**
49
```typescript
50
import { useMuiComponent } from "@rjsf/material-ui";
51
52
function CustomWidget(props: WidgetProps) {
53
const { TextField, Button } = useMuiComponent();
54
55
return (
56
<TextField
57
value={props.value}
58
onChange={(e) => props.onChange(e.target.value)}
59
/>
60
);
61
}
62
```
63
64
## Context Types
65
66
### MaterialUIContextProps (v4)
67
68
Interface defining Material UI v4 component structure:
69
70
```typescript { .api }
71
interface MaterialUIContextProps {
72
Box: React.ComponentType<BoxProps>;
73
Button: React.ComponentType<ButtonProps>;
74
Checkbox: React.ComponentType<CheckboxProps>;
75
Divider: React.ComponentType<DividerProps>;
76
Grid: React.ComponentType<GridProps>;
77
FormControl: React.ComponentType<FormControlProps>;
78
FormControlLabel: React.ComponentType<FormControlLabelProps>;
79
FormGroup: React.ComponentType<FormGroupProps>;
80
FormHelperText: React.ComponentType<FormHelperTextProps>;
81
FormLabel: React.ComponentType<FormLabelProps>;
82
IconButton: React.ComponentType<IconButtonProps>;
83
Input: React.ComponentType<InputProps>;
84
InputLabel: React.ComponentType<InputLabelProps>;
85
List: React.ComponentType<ListProps>;
86
ListItem: React.ComponentType<ListItemProps>;
87
ListItemIcon: React.ComponentType<ListItemIconProps>;
88
ListItemText: React.ComponentType<ListItemTextProps>;
89
MenuItem: React.ComponentType<MenuItemProps>;
90
Paper: React.ComponentType<PaperProps>;
91
Radio: React.ComponentType<RadioProps>;
92
RadioGroup: React.ComponentType<RadioGroupProps>;
93
Slider: React.ComponentType<SliderProps>;
94
TextField: React.ComponentType<Omit<TextFieldProps, 'color' | 'variant'>>;
95
Typography: React.ComponentType<TypographyProps>;
96
AddIcon: React.ComponentType<SvgIconProps>;
97
ArrowDownwardIcon: React.ComponentType<SvgIconProps>;
98
ArrowUpwardIcon: React.ComponentType<SvgIconProps>;
99
ErrorIcon: React.ComponentType<SvgIconProps>;
100
RemoveIcon: React.ComponentType<SvgIconProps>;
101
}
102
```
103
104
### Mui5ContextProps (v5)
105
106
Interface defining Material UI v5 component structure:
107
108
```typescript { .api }
109
interface Mui5ContextProps {
110
Box: React.ComponentType<BoxProps>;
111
Button: React.ComponentType<ButtonProps>;
112
Checkbox: React.ComponentType<CheckboxProps>;
113
Divider: React.ComponentType<DividerProps>;
114
Grid: React.ComponentType<GridProps>;
115
FormControl: React.ComponentType<FormControlProps>;
116
FormControlLabel: React.ComponentType<FormControlLabelProps>;
117
FormGroup: React.ComponentType<FormGroupProps>;
118
FormHelperText: React.ComponentType<FormHelperTextProps>;
119
FormLabel: React.ComponentType<FormLabelProps>;
120
IconButton: React.ComponentType<IconButtonProps>;
121
Input: React.ComponentType<OutlinedInputProps>; // Different from v4
122
InputLabel: React.ComponentType<InputLabelProps>;
123
List: React.ComponentType<ListProps>;
124
ListItem: React.ComponentType<ListItemProps>;
125
ListItemIcon: React.ComponentType<ListItemIconProps>;
126
ListItemText: React.ComponentType<ListItemTextProps>;
127
MenuItem: React.ComponentType<MenuItemProps>;
128
Paper: React.ComponentType<PaperProps>;
129
Radio: React.ComponentType<RadioProps>;
130
RadioGroup: React.ComponentType<RadioGroupProps>;
131
Slider: React.ComponentType<SliderProps>;
132
TextField: React.ComponentType<Omit<TextFieldProps, 'color' | 'variant'>>;
133
Typography: React.ComponentType<TypographyProps>;
134
AddIcon: React.ComponentType<SvgIconProps>;
135
ArrowDownwardIcon: React.ComponentType<SvgIconProps>;
136
ArrowUpwardIcon: React.ComponentType<SvgIconProps>;
137
ErrorIcon: React.ComponentType<SvgIconProps>;
138
RemoveIcon: React.ComponentType<SvgIconProps>;
139
}
140
```
141
142
## Context Providers
143
144
### MaterialUIContext (v4)
145
146
Context value object containing Material UI v4 component references:
147
148
```typescript { .api }
149
/**
150
* Object containing @material-ui/core v4 component references
151
* Null if Material UI v4 dependencies are not available
152
*/
153
declare const MaterialUIContext: MaterialUIContextProps | null;
154
```
155
156
### Mui5Context (v5)
157
158
Context value object containing Material UI v5 component references:
159
160
```typescript { .api }
161
/**
162
* Object containing @mui/material v5 component references
163
* Null if Material UI v5 dependencies are not available
164
*/
165
declare const Mui5Context: Mui5ContextProps | null;
166
```
167
168
## Usage Examples
169
170
### Custom Widget with Context
171
172
```typescript
173
import { useMuiComponent } from "@rjsf/material-ui";
174
import { WidgetProps } from "@rjsf/core";
175
176
const CustomTextWidget: React.FC<WidgetProps> = (props) => {
177
const { TextField, FormControl, FormHelperText } = useMuiComponent();
178
179
return (
180
<FormControl fullWidth>
181
<TextField
182
id={props.id}
183
label={props.label}
184
value={props.value || ""}
185
onChange={(event) => props.onChange(event.target.value)}
186
onBlur={() => props.onBlur && props.onBlur(props.id, props.value)}
187
onFocus={() => props.onFocus && props.onFocus(props.id, props.value)}
188
disabled={props.disabled}
189
readonly={props.readonly}
190
required={props.required}
191
error={props.rawErrors && props.rawErrors.length > 0}
192
/>
193
{props.rawErrors && props.rawErrors.length > 0 && (
194
<FormHelperText error>
195
{props.rawErrors.join(", ")}
196
</FormHelperText>
197
)}
198
</FormControl>
199
);
200
};
201
```
202
203
### Context-Aware Component
204
205
```typescript
206
import { useMuiComponent } from "@rjsf/material-ui";
207
208
const VersionAwareComponent: React.FC = () => {
209
const components = useMuiComponent();
210
211
// Detect version by checking component differences
212
const isV5 = 'Input' in components &&
213
components.Input.toString().includes('OutlinedInput');
214
215
return (
216
<div>
217
<p>Using Material UI {isV5 ? 'v5' : 'v4'}</p>
218
<components.Button variant="contained">
219
Click me
220
</components.Button>
221
</div>
222
);
223
};
224
```
225
226
### Custom Context Provider
227
228
```typescript
229
import { MuiComponentContext } from "@rjsf/material-ui";
230
import * as MuiV5 from "@mui/material";
231
import * as MuiIcons from "@mui/icons-material";
232
233
const customContextValue: Mui5ContextProps = {
234
...MuiV5,
235
AddIcon: MuiIcons.Add,
236
ArrowDownwardIcon: MuiIcons.ArrowDownward,
237
ArrowUpwardIcon: MuiIcons.ArrowUpward,
238
ErrorIcon: MuiIcons.Error,
239
RemoveIcon: MuiIcons.Remove,
240
};
241
242
function CustomContextProvider({ children }: { children: React.ReactNode }) {
243
return (
244
<MuiComponentContext.Provider value={customContextValue}>
245
{children}
246
</MuiComponentContext.Provider>
247
);
248
}
249
```
250
251
### Error Handling
252
253
```typescript
254
import { useMuiComponent } from "@rjsf/material-ui";
255
256
const SafeWidget: React.FC<WidgetProps> = (props) => {
257
try {
258
const { TextField } = useMuiComponent();
259
260
return (
261
<TextField
262
value={props.value}
263
onChange={(e) => props.onChange(e.target.value)}
264
/>
265
);
266
} catch (error) {
267
return (
268
<div style={{ color: 'red' }}>
269
Material UI components not available: {error.message}
270
</div>
271
);
272
}
273
};
274
```
275
276
### Testing with Mock Context
277
278
```typescript
279
import { render } from "@testing-library/react";
280
import { MuiComponentContext } from "@rjsf/material-ui";
281
282
const mockContext: Partial<MaterialUIContextProps> = {
283
TextField: ({ value, onChange }) => (
284
<input value={value} onChange={(e) => onChange(e)} />
285
),
286
Button: ({ children, onClick }) => (
287
<button onClick={onClick}>{children}</button>
288
),
289
};
290
291
function renderWithMockContext(component: React.ReactElement) {
292
return render(
293
<MuiComponentContext.Provider value={mockContext as any}>
294
{component}
295
</MuiComponentContext.Provider>
296
);
297
}
298
299
// Usage in tests
300
test("widget renders correctly", () => {
301
const { getByRole } = renderWithMockContext(<CustomWidget {...props} />);
302
expect(getByRole("textbox")).toBeInTheDocument();
303
});
304
```
305
306
## Context Architecture
307
308
The context system provides several key benefits:
309
310
1. **Version Abstraction**: Widgets don't need to know which Material UI version is being used
311
2. **Dependency Injection**: Components are provided rather than imported directly
312
3. **Testing Support**: Easy to mock components for unit testing
313
4. **Bundle Optimization**: Only the required Material UI version is included in the bundle
314
5. **Runtime Detection**: Graceful handling when dependencies are missing
315
316
## Error States
317
318
The context system handles several error conditions:
319
320
- **Missing Dependencies**: Shows warning when Material UI packages aren't installed
321
- **Version Conflicts**: Detects and handles mixed v4/v5 installations
322
- **Context Unavailable**: Throws descriptive error when useMuiComponent is called outside provider
323
- **Component Missing**: Graceful degradation when specific components aren't available
324
325
The form wrappers automatically display user-friendly warnings when Material UI dependencies are not available, preventing runtime crashes and providing clear guidance for resolution.