Customizing material-ui fields and widgets
Unlike most other themes, the material-ui theme supports the two distinct version of Material UI (versions 4 and 5) side-by-side.
Material UI version 4 is provided by the scoped packages under @material-ui and version 5 is provided by the scoped packages under @mui.
The components used by @rjsf/material-ui for Material UI version 4 and version 5 have identical names and props.
As a result, all of the fields and widgets provided by the theme are identical as well.
The trick to making the two versions function side-by-side, was done by creating a React context, MuiComponentContext, that provides the appropriate set of components used by theme, for the particular scoped package.
In addition to this context, a custom hook, useMuiComponent(), is provided to allow quick access to that component set.
Example of a custom widget for @rjsf/material-ui
Here is an update to the MyCustomWidget for the material-ui theme
const schema = {
  type: "string"
};
import { useMuiComponent } from '@rjsf/material-ui/v4';
function MyCustomWidget(props) {
  const { options, ...otherProps } = props;
  const { color, backgroundColor } = options;
  const { TextInput } = useMuiComponent();
  return <TextInput {...otherProps} style={{ color, backgroundColor }} />;
}
MyCustomWidget.defaultProps = {
  options: {
    color: "red"
  }
};
const uiSchema = {
  "ui:widget": MyCustomWidget,
  "ui:options": {
    backgroundColor: "yellow"
  }
};
// renders red on yellow input
render((
  <Form schema={schema}
        uiSchema={uiSchema} />
), document.getElementById("app"));
Example of a custom field for @rjsf/material-ui
Here is an update to the GeoPosition for the material-ui theme
const schema = {
  type: "object",
  required: ["lat", "lon"],
  properties: {
    lat: { type: "number"},
    lon: { type: "number" }
  }
};
import { useMuiComponent } from '@rjsf/material-ui/v4';
// Define a custom component for handling the root position object
function GeoPosition(props) {
  const { lat, lon } = props.formData;
  const { Box, TextInput } = useMuiComponent();
  const onChangeLat = (event) => {
    const { target: { value } } = event;
    const newData = { ...props.formData, lat: value };
    props.onChange(newData);
  };
  const onChangeLon = (event) => {
    const { target: { value } } = event;
    const newData = { ...props.formData, lon: value };
    props.onChange(newData);
  };
  return (
    <Box>
      <TextInput type="number" value={lat} onChange={onChangeLat} />
      <TextInput type="number" value={lon} onChange={onChangeLon} />
    </Box>
  );
}
// Define the custom field component to use for the root object
const uiSchema = { "ui:field": "geo" };
// Define the custom field components to register; here our "geo"
// custom field component
const fields = { geo: GeoPosition };
// Render the form with all the properties we just defined passed
// as props
render((
  <Form
    schema={schema}
    uiSchema={uiSchema}
    fields={fields} />
), document.getElementById("app"));