Some checks failed
No response / noResponse (push) Has been cancelled
CI / Continuous releases (push) Has been cancelled
CI / test-dev (macos-latest) (push) Has been cancelled
CI / test-dev (ubuntu-latest) (push) Has been cancelled
CI / test-dev (windows-latest) (push) Has been cancelled
Maintenance / main (push) Has been cancelled
Scorecards supply-chain security / Scorecards analysis (push) Has been cancelled
CodeQL / Analyze (push) Has been cancelled
474 lines
15 KiB
Markdown
474 lines
15 KiB
Markdown
# Migration from v3 to v4
|
||
|
||
<p class="description">Yeah, v4 has been released!</p>
|
||
|
||
Looking for the v3 docs? You can [find the latest version here](https://mui.com/versions/).
|
||
|
||
:::info
|
||
This document is a work in progress.
|
||
Have you upgraded your site and run into something that's not covered here?
|
||
[Add your changes on GitHub](https://github.com/mui/material-ui/blob/HEAD/docs/data/material/migration/migration-v3/migration-v3.md).
|
||
:::
|
||
|
||
## Introduction
|
||
|
||
This is a reference for upgrading your site from Material UI v3 to v4.
|
||
While there's a lot covered here, you probably won't need to do everything for your site.
|
||
We'll do our best to keep things easy to follow, and as sequential as possible so you can quickly get rocking on v4!
|
||
|
||
## Why you should migrate
|
||
|
||
This documentation page covers the **how** of migrating from v3 to v4.
|
||
The **why** is covered in the [release blog post on Medium](https://mui.com/blog/material-ui-v4-is-out/).
|
||
|
||
## Updating your dependencies
|
||
|
||
The very first thing you will need to do is to update your dependencies.
|
||
|
||
### Update Material UI version
|
||
|
||
You need to update your `package.json` to use the latest version of Material UI.
|
||
|
||
```json
|
||
"dependencies": {
|
||
"@material-ui/core": "^4.0.0"
|
||
}
|
||
```
|
||
|
||
Or run
|
||
|
||
```bash
|
||
npm install @material-ui/core
|
||
|
||
or
|
||
|
||
yarn add @material-ui/core
|
||
```
|
||
|
||
### Update React version
|
||
|
||
The minimum required version of React was increased from `react@^16.3.0` to `react@^16.8.0`.
|
||
This allows us to rely on [Hooks](https://react.dev/reference/react/hooks) (we no longer use the class API).
|
||
|
||
### Update Material UI Styles version
|
||
|
||
If you were previously using `@material-ui/styles` with v3 you need to update your `package.json` to use the latest version of Material UI Styles.
|
||
|
||
```json
|
||
"dependencies": {
|
||
"@material-ui/styles": "^4.0.0"
|
||
}
|
||
```
|
||
|
||
Or run
|
||
|
||
```bash
|
||
npm install @material-ui/styles
|
||
|
||
or
|
||
|
||
yarn add @material-ui/styles
|
||
```
|
||
|
||
## Handling breaking changes
|
||
|
||
### Core
|
||
|
||
- Every component forward their ref.
|
||
This is implemented by using `React.forwardRef()`.
|
||
This affects the internal component tree and display name and therefore might break shallow or snapshot tests.
|
||
`innerRef` will no longer return a ref to the instance (or nothing if the inner component is a function component) but a ref to its root component.
|
||
The corresponding API docs list the root component.
|
||
|
||
### Styles
|
||
|
||
- ⚠️ Material UI depends on JSS v10. JSS v10 is not backward compatible with v9.
|
||
Make sure JSS v9 is not installed in your environment.
|
||
(Removing `react-jss` from your `package.json` can help).
|
||
The StylesProvider component replaces the JssProvider one.
|
||
- Remove the first option argument of `withTheme()`.
|
||
(The first argument was a placeholder for a potential future option that never arose.)
|
||
|
||
It matches the [emotion API](https://emotion.sh/docs/introduction) and the [styled-components API](https://styled-components.com).
|
||
|
||
```diff
|
||
-const DeepChild = withTheme()(DeepChildRaw);
|
||
+const DeepChild = withTheme(DeepChildRaw);
|
||
```
|
||
|
||
- Rename `convertHexToRGB` to `hexToRgb`.
|
||
|
||
```diff
|
||
-import { convertHexToRgb } from '@material-ui/core/styles/colorManipulator';
|
||
+import { hexToRgb } from '@material-ui/core/styles';
|
||
```
|
||
|
||
- Scope the [keyframes API](https://cssinjs.org/jss-syntax/#keyframes-animation). You should apply the following changes in your codebase.
|
||
It helps isolating the animation logic:
|
||
|
||
```diff
|
||
rippleVisible: {
|
||
opacity: 0.3,
|
||
- animation: 'mui-ripple-enter 100ms cubic-bezier(0.4, 0, 0.2, 1)',
|
||
+ animation: '$mui-ripple-enter 100ms cubic-bezier(0.4, 0, 0.2, 1)',
|
||
},
|
||
'@keyframes mui-ripple-enter': {
|
||
'0%': {
|
||
opacity: 0.1,
|
||
},
|
||
'100%': {
|
||
opacity: 0.3,
|
||
},
|
||
},
|
||
```
|
||
|
||
### Theme
|
||
|
||
- The `theme.palette.augmentColor()` method no longer performs a side effect on its input color.
|
||
To use it correctly, you have to use the returned value.
|
||
|
||
```diff
|
||
-const background = { main: color };
|
||
-theme.palette.augmentColor(background);
|
||
+const background = theme.palette.augmentColor({ main: color });
|
||
|
||
console.log({ background });
|
||
```
|
||
|
||
- You can safely remove the next variant from the theme creation:
|
||
|
||
```diff
|
||
typography: {
|
||
- useNextVariants: true,
|
||
},
|
||
```
|
||
|
||
- `theme.spacing.unit` usage is deprecated, you can use the new API:
|
||
|
||
```diff
|
||
label: {
|
||
[theme.breakpoints.up('sm')]: {
|
||
- paddingTop: theme.spacing.unit * 12,
|
||
+ paddingTop: theme.spacing(12),
|
||
},
|
||
}
|
||
```
|
||
|
||
_Tip: you can provide more than 1 argument: `theme.spacing(1, 2) // = '8px 16px'`_.
|
||
|
||
You can use [the migration helper](https://github.com/mui/material-ui/tree/master/packages/mui-codemod/README.md#theme-spacing-api) on your project to make this smoother.
|
||
|
||
### Layout
|
||
|
||
- [Grid] In order to support arbitrary spacing values and to remove the need to mentally count by 8, we are changing the spacing API:
|
||
|
||
```diff
|
||
/**
|
||
* Defines the space between the type `item` component.
|
||
* It can only be used on a type `container` component.
|
||
*/
|
||
- spacing: PropTypes.oneOf([0, 8, 16, 24, 32, 40]),
|
||
+ spacing: PropTypes.oneOf([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]),
|
||
```
|
||
|
||
Going forward, you can use the theme to implement [a custom Grid spacing transformation function](/system/spacing/#transformation).
|
||
|
||
- [Container] Moved from `@material-ui/lab` to `@material-ui/core`.
|
||
|
||
```diff
|
||
-import Container from '@material-ui/lab/Container';
|
||
+import Container from '@material-ui/core/Container';
|
||
```
|
||
|
||
### TypeScript
|
||
|
||
#### `value` type
|
||
|
||
Normalized `value` prop type for input components to use `unknown`. This affects
|
||
`InputBase`, `NativeSelect`, `OutlinedInput`, `Radio`, `RadioGroup`, `Select`, `SelectInput`, `Switch`, `TextArea`, and `TextField`.
|
||
|
||
```diff
|
||
function MySelect({ children }) {
|
||
- const handleChange = (event: any, value: string) => {
|
||
+ const handleChange = (event: any, value: unknown) => {
|
||
// handle value
|
||
};
|
||
|
||
return <Select onChange={handleChange}>{children}</Select>
|
||
}
|
||
```
|
||
|
||
This change is explained in more detail in the [TypeScript guide](/material-ui/guides/typescript/#handling-value-and-event-handlers)
|
||
|
||
### Button
|
||
|
||
- [Button] Remove the deprecated button variants (flat, raised and fab):
|
||
|
||
```diff
|
||
-<Button variant="raised" />
|
||
+<Button variant="contained" />
|
||
```
|
||
|
||
```diff
|
||
-<Button variant="flat" />
|
||
+<Button variant="text" />
|
||
```
|
||
|
||
```diff
|
||
-import Button from '@material-ui/core/Button';
|
||
-<Button variant="fab" />
|
||
+import Fab from '@material-ui/core/Fab';
|
||
+<Fab />
|
||
```
|
||
|
||
```diff
|
||
-import Button from '@material-ui/core/Button';
|
||
-<Button variant="extendedFab" />
|
||
+import Fab from '@material-ui/core/Fab';
|
||
+<Fab variant="extended" />
|
||
```
|
||
|
||
- [ButtonBase] The component passed to the `component` prop needs to be able to hold a ref.
|
||
The [composition guide](/material-ui/guides/composition/#caveat-with-refs) explains the migration strategy.
|
||
|
||
This also applies to `BottomNavigationAction`, `Button`, `CardActionArea`, `Checkbox`, `ExpansionPanelSummary`, `Fab`, `IconButton`, `MenuItem`, `Radio`, `StepButton`, `Tab`, `TableSortLabel` as well as `ListItem` if the `button` prop is true.
|
||
|
||
### Card
|
||
|
||
- [CardActions] Rename the `disableActionSpacing` prop to `disableSpacing`.
|
||
- [CardActions] Remove the `disableActionSpacing` CSS class.
|
||
- [CardActions] Rename the `action` CSS class to `spacing`.
|
||
|
||
### ClickAwayListener
|
||
|
||
- [ClickAwayListener] Hide react-event-listener props.
|
||
|
||
### Dialog
|
||
|
||
- [DialogActions] Rename the `disableActionSpacing` prop to `disableSpacing`.
|
||
- [DialogActions] Rename the `action` CSS class to `spacing`.
|
||
- [DialogContentText] Use typography variant `body1` instead of `subtitle1`.
|
||
- [Dialog] The child needs to be able to hold a ref. The [composition guide](/material-ui/guides/composition/#caveat-with-refs)
|
||
explains the migration strategy.
|
||
|
||
### Divider
|
||
|
||
- [Divider] Remove the deprecated `inset` prop.
|
||
|
||
```diff
|
||
-<Divider inset />
|
||
+<Divider variant="inset" />
|
||
```
|
||
|
||
### ExpansionPanel
|
||
|
||
- [ExpansionPanelActions] Rename the `action` CSS class to `spacing`.
|
||
- [ExpansionPanel] Increase the CSS specificity of the `disabled` and `expanded` style rules.
|
||
- [ExpansionPanel] Rename the `CollapseProps` prop to `TransitionProps`.
|
||
|
||
### List
|
||
|
||
- [List] Rework the list components to match the specification:
|
||
- The `ListItemAvatar` component is required when using an avatar.
|
||
- The `ListItemIcon` component is required when using a left checkbox.
|
||
- The `edge` property should be set on the icon buttons.
|
||
|
||
- [List] `dense` no longer reduces the top and bottom padding of the `List` element.
|
||
- [ListItem] Increase the CSS specificity of the `disabled` and `focusVisible` style rules.
|
||
|
||
### Menu
|
||
|
||
- [MenuItem] Remove the fixed height of the MenuItem.
|
||
The padding and line-height are used by the browser to compute the height.
|
||
|
||
### Modal
|
||
|
||
- [Modal] The child needs to be able to hold a ref. The [composition guide](/material-ui/guides/composition/#caveat-with-refs) explains
|
||
the migration strategy.
|
||
|
||
This also applies to `Dialog` and `Popover`.
|
||
|
||
- [Modal] Remove the classes customization API for the Modal component (-74% bundle size reduction when used standalone).
|
||
- [Modal] event.defaultPrevented is now ignored.
|
||
The new logic closes the Modal even if `event.preventDefault()` is called on the key down escape event.
|
||
`event.preventDefault()` is meant to stop default behaviors like clicking a checkbox to check it, hitting a button to submit a form, and hitting left arrow to move the cursor in a text input etc.
|
||
Only special HTML elements have these default behaviors.
|
||
You should use `event.stopPropagation()` if you don't want to trigger an `onClose` event on the modal.
|
||
|
||
### Paper
|
||
|
||
- [Paper] Reduce the default elevation.
|
||
Change the default Paper elevation to match the Card and the Expansion Panel:
|
||
|
||
```diff
|
||
-<Paper />
|
||
+<Paper elevation={2} />
|
||
```
|
||
|
||
This affects the `ExpansionPanel` as well.
|
||
|
||
### Portal
|
||
|
||
- [Portal] The child needs to be able to hold a ref when `disablePortal` is used. The [composition guide](/material-ui/guides/composition/#caveat-with-refs) explains
|
||
the migration strategy.
|
||
|
||
### Slide
|
||
|
||
- [Slide] The child needs to be able to hold a ref. The [composition guide](/material-ui/guides/composition/#caveat-with-refs) explains
|
||
the migration strategy.
|
||
|
||
### Slider
|
||
|
||
- [Slider] Move from `@material-ui/lab` to `@material-ui/core`.
|
||
|
||
```diff
|
||
-import Slider from '@material-ui/lab/Slider'
|
||
+import Slider from '@material-ui/core/Slider'
|
||
```
|
||
|
||
### Switch
|
||
|
||
- [Switch] Refactor the implementation to make it easier to override the styles.
|
||
Rename the class names to match the specification wording:
|
||
|
||
```diff
|
||
-icon
|
||
-bar
|
||
+thumb
|
||
+track
|
||
```
|
||
|
||
### Snackbar
|
||
|
||
- [Snackbar] Match the new specification.
|
||
- Change the dimensions
|
||
- Change the default transition from `Slide` to `Grow`.
|
||
|
||
### SvgIcon
|
||
|
||
- [SvgIcon] Rename nativeColor -> htmlColor.
|
||
React solved the same problem with the `for` HTML attribute, they have decided to call the prop `htmlFor`. This change follows the same reasoning.
|
||
|
||
```diff
|
||
-<AddIcon nativeColor="#fff" />
|
||
+<AddIcon htmlColor="#fff" />
|
||
```
|
||
|
||
### Tabs
|
||
|
||
- [Tab] Remove the `labelContainer`, `label` and `labelWrapped` class keys for simplicity.
|
||
This has allowed us to remove 2 intermediary DOM elements.
|
||
You should be able to move the custom styles to the `root` class key.
|
||
|
||

|
||
|
||
- [Tabs] Remove deprecated fullWidth and scrollable props:
|
||
|
||
```diff
|
||
-<Tabs fullWidth scrollable />
|
||
+<Tabs variant="scrollable" />
|
||
```
|
||
|
||
### Table
|
||
|
||
- [TableCell] Remove the deprecated `numeric` property:
|
||
|
||
```diff
|
||
-<TableCell numeric>{row.calories}</TableCell>
|
||
+<TableCell align="right">{row.calories}</TableCell>
|
||
```
|
||
|
||
- [TableRow] Remove the fixed height CSS property.
|
||
The cell height is computed by the browser using the padding and line-height.
|
||
- [TableCell] Move the `dense` mode to a different property:
|
||
|
||
```diff
|
||
-<TableCell padding="dense" />
|
||
+<TableCell size="small" />
|
||
```
|
||
|
||
- [TablePagination] The component no longer tries to fix invalid (`page`, `count`, `rowsPerPage`) property combinations. It raises a warning instead.
|
||
|
||
### TextField
|
||
|
||
- [InputLabel] You should be able to override all the styles of the FormLabel component using the CSS API of the InputLabel component.
|
||
The `FormLabelClasses` property has been removed.
|
||
|
||
```diff
|
||
<InputLabel
|
||
- FormLabelClasses={{ asterisk: 'bar' }}
|
||
+ classes={{ asterisk: 'bar' }}
|
||
>
|
||
Foo
|
||
</InputLabel>
|
||
```
|
||
|
||
- [InputBase] Change the default box sizing model.
|
||
It uses the following CSS now:
|
||
|
||
```css
|
||
box-sizing: border-box;
|
||
```
|
||
|
||
This solves issues with the `fullWidth` prop.
|
||
|
||
- [InputBase] Remove the `inputType` class from `InputBase`.
|
||
|
||
### Tooltip
|
||
|
||
- [Tooltip] The child needs to be able to hold a ref. The [composition guide](/material-ui/guides/composition/#caveat-with-refs) explains
|
||
the migration strategy.
|
||
- [Tooltip] Appears only after focus-visible focus instead of any focus.
|
||
|
||
### Typography
|
||
|
||
- [Typography] Remove the deprecated typography variants. You can upgrade by performing the following replacements:
|
||
- display4 => h1
|
||
- display3 => h2
|
||
- display2 => h3
|
||
- display1 => h4
|
||
- headline => h5
|
||
- title => h6
|
||
- subheading => subtitle1
|
||
- body2 => body1
|
||
- body1 (default) => body2 (default)
|
||
- [Typography] Remove the opinionated `display: block` default typography style.
|
||
You can use the new `display?: 'initial' | 'inline' | 'block';` property.
|
||
- [Typography] Rename the `headlineMapping` property to `variantMapping` to better align with its purpose.
|
||
|
||
```diff
|
||
-<Typography headlineMapping={headlineMapping}>
|
||
+<Typography variantMapping={variantMapping}>
|
||
```
|
||
|
||
- [Typography] Change the default variant from `body2` to `body1`.
|
||
A font size of 16px is a better default than 14px.
|
||
Bootstrap, material.io, and even the documentation use 16px as a default font size.
|
||
14px like Ant Design uses is understandable, as Chinese users have a different alphabet.
|
||
12px is recommended as the default font size for Japanese.
|
||
- [Typography] Remove the default color from the typography variants.
|
||
The color should inherit most of the time. It's the default behavior of the web.
|
||
- [Typography] Rename `color="default"` to `color="initial"` following the logic of [this thread](https://github.com/mui/material-ui/issues/13028).
|
||
The usage of _default_ should be avoided, it lacks semantic.
|
||
|
||
### Node
|
||
|
||
- [Drop node 6 support](https://github.com/nodejs/Release/blob/eb91c94681ea968a69bf4a4fe85c656ed44263b3/README.md#release-schedule), you should upgrade to node 8.
|
||
|
||
### UMD
|
||
|
||
- This change eases the use of Material UI with a CDN:
|
||
|
||
```diff
|
||
const {
|
||
Button,
|
||
TextField,
|
||
-} = window['material-ui'];
|
||
+} = MaterialUI;
|
||
```
|
||
|
||
It's consistent with other React projects:
|
||
- material-ui => MaterialUI
|
||
- react-dom => ReactDOM
|
||
- prop-types => PropTypes
|