Files
react-test/docs/data/material/migration/migration-v4/migrating-from-jss.md
how2ice 005cf56baf
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
init project
2025-12-12 14:26:25 +09:00

473 lines
15 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Migrating from JSS (optional)
<p class="description">This guide explains how to migrate from JSS to Emotion when updating from Material UI v4 to v5.</p>
## Material UI v5 migration
1. [Getting started](/material-ui/migration/migration-v4/)
2. [Breaking changes part one: style and theme](/material-ui/migration/v5-style-changes/)
3. [Breaking changes part two: components](/material-ui/migration/v5-component-changes/)
4. Migrating from JSS 👈 _you are here_
5. [Troubleshooting](/material-ui/migration/troubleshooting/)
## Migrating from JSS to Emotion
One of the biggest changes in v5 is the replacement of JSS for [Emotion](https://emotion.sh/docs/introduction) (or [styled-components](https://styled-components.com/) as an alternative) as a default styling solution .
Note that you may continue to use JSS for adding overrides for the components (for example `makeStyles`, `withStyles`) even after migrating to v5.
Then, if at any point you want to move over to the new styling engine, you can refactor your components progressively.
:::info
If you are using Next.js and you are not sure how to configure SSR to work with both Emotion & JSS, take a look a this [example project](https://github.com/mui/material-ui/tree/master/examples/material-ui-nextjs-ts-v4-v5-migration).
:::
This document reviews all the steps necessary to migrate away from JSS.
While you can use either of the following two options, the first is considered preferable:
### 1. Use styled or sx API
#### Codemod
We provide [a codemod](https://github.com/mui/material-ui/blob/master/packages/mui-codemod/README.md#jss-to-styled) to help migrate JSS styles to `styled` API, but this approach increases the CSS specificity.
:::info
Normally you wouldn't write styles like this.
But this is the best transformation that we could create with a codemod.
If you want to refine them later, you can refer to the examples shown in the sections below.
:::
```bash
npx @mui/codemod@latest v5.0.0/jss-to-styled <path>
```
Example transformation:
```diff
import Typography from '@mui/material/Typography';
-import makeStyles from '@mui/styles/makeStyles';
+import { styled } from '@mui/material/styles';
-const useStyles = makeStyles((theme) => ({
- root: {
- display: 'flex',
- alignItems: 'center',
- backgroundColor: theme.palette.primary.main
- },
- cta: {
- borderRadius: theme.shape.radius
- },
- content: {
- color: theme.palette.common.white,
- fontSize: 16,
- lineHeight: 1.7
- },
-}))
+const PREFIX = 'MyCard';
+const classes = {
+ root: `${PREFIX}-root`,
+ cta: `${PREFIX}-cta`,
+ content: `${PREFIX}-content`,
+}
+const Root = styled('div')(({ theme }) => ({
+ [`&.${classes.root}`]: {
+ display: 'flex',
+ alignItems: 'center',
+ backgroundColor: theme.palette.primary.main
+ },
+ [`& .${classes.cta}`]: {
+ borderRadius: theme.shape.radius
+ },
+ [`& .${classes.content}`]: {
+ color: theme.palette.common.white,
+ fontSize: 16,
+ lineHeight: 1.7
+ },
+}))
export const MyCard = () => {
- const classes = useStyles();
return (
- <div className={classes.root}>
+ <Root className={classes.root}>
{/* The benefit of this approach is that the code inside Root stays the same. */}
<Typography className={classes.content}>...</Typography>
<Button className={classes.cta}>Go</Button>
- </div>
+ </Root>
)
}
```
:::success
You should run this codemod on a small chunk of files and then check the changes before continuing, because in some cases you might need to adjust the code after the transformation—this codemod won't cover all cases.
:::
#### Manual
We recommend `sx` API over `styled` for creating responsive styles or overriding minor CSS.
[Read more about `sx` here](/system/getting-started/the-sx-prop/).
```diff
import Chip from '@mui/material/Chip';
-import makeStyles from '@mui/styles/makeStyles';
+import Box from '@mui/material/Box';
-const useStyles = makeStyles((theme) => ({
- wrapper: {
- display: 'flex',
- },
- chip: {
- padding: theme.spacing(1, 1.5),
- boxShadow: theme.shadows[1],
- }
-}));
function App() {
- const classes = useStyles();
return (
- <div className={classes.wrapper}>
- <Chip className={classes.chip} label="Chip" />
- </div>
+ <Box sx={{ display: 'flex' }}>
+ <Chip label="Chip" sx={{ py: 1, px: 1.5, boxShadow: 1 }} />
+ </Box>
);
}
```
In some cases, you might want to create multiple styled components in a file instead of increasing CSS specificity.
For example:
```diff
-import makeStyles from '@mui/styles/makeStyles';
+import { styled } from '@mui/material/styles';
-const useStyles = makeStyles((theme) => ({
- root: {
- display: 'flex',
- alignItems: 'center',
- borderRadius: 20,
- background: theme.palette.grey[50],
- },
- label: {
- color: theme.palette.primary.main,
- }
-}))
+const Root = styled('div')(({ theme }) => ({
+ display: 'flex',
+ alignItems: 'center',
+ borderRadius: 20,
+ background: theme.palette.grey[50],
+}))
+const Label = styled('span')(({ theme }) => ({
+ color: theme.palette.primary.main,
+}))
function Status({ label }) {
- const classes = useStyles();
return (
- <div className={classes.root}>
- {icon}
- <span className={classes.label}>{label}</span>
- </div>
+ <Root>
+ {icon}
+ <Label>{label}</Label>
+ </Root>
)
}
```
:::success
[This jss-to-styled tool](https://siriwatk.dev/tool/jss-to-styled) helps convert JSS to multiple styled components without increasing CSS specificity.
This tool is _not_ maintained by MUI.
:::
### 2. Use [tss-react](https://github.com/garronej/tss-react)
:::error
This API will not work if you are [using `styled-components` as the underlying styling engine in place of `@emotion`](/material-ui/integrations/interoperability/#styled-components).
:::
The API is similar to JSS `makeStyles`, but under the hood, it uses `@emotion/react`.
It also features much better TypeScript support than v4's `makeStyles`.
In order to use it, you'll need to add it to your project's dependencies:
With npm:
```bash
npm install tss-react
```
With yarn:
```bash
yarn add tss-react
```
#### Codemod
We provide [a codemod](https://github.com/mui/material-ui/blob/master/packages/mui-codemod/README.md#jss-to-tss-react) to help migrate JSS styles to the `tss-react` API.
```bash
npx @mui/codemod@latest v5.0.0/jss-to-tss-react <path>
```
Example transformation:
```diff
import * as React from 'react';
-import makeStyles from '@material-ui/styles/makeStyles';
+import { makeStyles } from 'tss-react/mui';
import Button from '@mui/material/Button';
import Link from '@mui/material/Link';
-const useStyles = makeStyles((theme) => {
+const useStyles = makeStyles()((theme) => {
return {
root: {
color: theme.palette.primary.main,
},
apply: {
marginRight: theme.spacing(2),
},
};
});
function Apply() {
- const classes = useStyles();
+ const { classes } = useStyles();
return (
<div className={classes.root}>
<Button component={Link} to="https://support.mui.com" className={classes.apply}>
Apply now
</Button>
</div>
);
}
export default Apply;
```
If you were using the `$` syntax and `clsx` to combine multiple CSS classes,
the transformation would look like this:
```diff
import * as React from 'react';
-import { makeStyles } from '@material-ui/core/styles';
-import clsx from 'clsx';
+import { makeStyles } from 'tss-react/mui';
-const useStyles = makeStyles((theme) => ({
+const useStyles = makeStyles<void, 'child' | 'small'>()((theme, _params, classes) => ({
parent: {
padding: 30,
- '&:hover $child': {
+ [`&:hover .${classes.child}`]: {
backgroundColor: 'red',
},
},
small: {},
child: {
backgroundColor: 'blue',
height: 50,
- '&$small': {
+ [`&.${classes.small}`]: {
backgroundColor: 'lightblue',
height: 30
}
},
}));
function App() {
- const classes = useStyles();
+ const { classes, cx } = useStyles();
return (
<div className={classes.parent}>
<div className={classes.child}>
Background turns red when the mouse hovers over the parent.
</div>
- <div className={clsx(classes.child, classes.small)}>
+ <div className={cx(classes.child, classes.small)}>
Background turns red when the mouse hovers over the parent.
I am smaller than the other child.
</div>
</div>
);
}
export default App;
```
:::error
When using JavaScript (rather than TypeScript), remove `<void, 'child' | 'small'>`.
:::
The following is a comprehensive example using the `$` syntax, `useStyles()` parameters, merging in classes from a `classes` prop ([see doc](https://docs.tss-react.dev/your-own-classes-prop)) and [an explicit name for the stylesheet](https://docs.tss-react.dev/api/makestyles#naming-the-stylesheets-useful-for-debugging-and-theme-style-overrides).
```diff
-import clsx from 'clsx';
-import { makeStyles, createStyles } from '@material-ui/core/styles';
+import { makeStyles } from 'tss-react/mui';
-const useStyles = makeStyles((theme) => createStyles<
- 'root' | 'small' | 'child', {color: 'primary' | 'secondary', padding: number}
->
-({
- root: ({color, padding}) => ({
+const useStyles = makeStyles<{color: 'primary' | 'secondary', padding: number}, 'child' | 'small'>({name: 'App'})((theme, { color, padding }, classes) => ({
+ root: {
padding: padding,
- '&:hover $child': {
+ [`&:hover .${classes.child}`]: {
backgroundColor: theme.palette[color].main,
}
- }),
+ },
small: {},
child: {
border: '1px solid black',
height: 50,
- '&$small': {
+ [`&.${classes.small}`]: {
height: 30
}
}
-}), {name: 'App'});
+}));
function App({classes: classesProp}: {classes?: any}) {
- const classes = useStyles({color: 'primary', padding: 30, classes: classesProp});
+ const { classes, cx } = useStyles({
+ color: 'primary',
+ padding: 30
+ }, {
+ props: {
+ classes: classesProp
+ }
+ });
return (
<div className={classes.root}>
<div className={classes.child}>
The Background take the primary theme color when the mouse hovers the parent.
</div>
- <div className={clsx(classes.child, classes.small)}>
+ <div className={cx(classes.child, classes.small)}>
The Background take the primary theme color when the mouse hovers the parent.
I am smaller than the other child.
</div>
</div>
);
}
export default App;
```
After running the codemod, search your code for "TODO jss-to-tss-react codemod" to find cases that the codemod could not handle reliably.
There may be other cases beyond those with TODO comments that are not handled fully by the codemod—particularly if parts of the styles are returned by functions.
If the styles buried within a function use the `$` syntax or `useStyles` params, then those styles won't be migrated appropriately.
:::error
You should drop [`clsx`](https://www.npmjs.com/package/clsx) in favor of [`cx`](https://emotion.sh/docs/@emotion/css#cx).
The key advantage of `cx` is that it detects Emotion-generated class names to ensure that styles are overwritten in the correct order.
The default precedence of styles from multiple CSS classes is different between JSS and tss-react and some manual re-ordering of `cx` parameters
may be necessary—see [this issue comment](https://github.com/mui/material-ui/pull/31802#issuecomment-1093478971) for more details.
:::
To ensure that your class names always includes the actual name of your components, you can provide the `name` as an implicitly named key (`name: { App }`).
See [this tss-react doc](https://docs.tss-react.dev/api/makestyles#naming-the-stylesheets-useful-for-debugging-and-theme-style-overrides) for details.
You may end up with ESLint warnings [like this one](https://user-images.githubusercontent.com/6702424/148657837-eae48942-fb86-4516-abe4-5dc10f44f0be.png) if you deconstruct more than one item.
Don't hesitate to disable `eslint(prefer-const)`, [like this](https://github.com/thieryw/gitlanding/blob/b2b0c71d95cfd353979c86dfcfa1646ef1665043/.eslintrc.js#L17) in a regular project.
#### withStyles()
`tss-react` also features a [type-safe implementation](https://docs.tss-react.dev/api/withstyles) of [v4's `withStyles()`](https://v4.mui.com/styles/api/#withstyles-styles-options-higher-order-component).
:::info
The equivalent of the `$` syntax is also supported in tss's `withStyles()`.
[See doc](https://docs.tss-react.dev/nested-selectors#withstyles).
:::
```diff
-import Button from '@material-ui/core/Button';
+import Button from '@mui/material/Button';
-import withStyles from '@material-ui/styles/withStyles';
+import { withStyles } from 'tss-react/mui';
const MyCustomButton = withStyles(
+ Button,
(theme) => ({
root: {
minHeight: '30px',
},
textPrimary: {
color: theme.palette.text.primary,
},
'@media (min-width: 960px)': {
textPrimary: {
fontWeight: 'bold',
},
},
}),
-)(Button);
+);
export default MyCustomButton;
```
#### Theme style overrides
[Global theme overrides](https://v4.mui.com/customization/components/#global-theme-override) are supported out of the box by TSS.
Follow the instructions in the relevant section of the [Breaking changes](/material-ui/migration/v5-style-changes/#restructure-component-definitions) doc, and [provide a `name` to `makeStyles`](https://docs.tss-react.dev/api/makestyles#naming-the-stylesheets-useful-for-debugging-and-theme-style-overrides).
In Material UI v5, [style overrides also accept callbacks](https://mui.com/material-ui/customization/theme-components/).
By default, TSS is only able to provide the theme.
If you want to provide the props and the `ownerState`, [please refer to this documentation](https://docs.tss-react.dev/mui-global-styleoverrides).
:::warning
tss-react is _not_ maintained by MUI.
If you have any question about how to setup SSR (Next.js), or if you are wondering
how to customize the `theme` object, please refer to the [tss-react documentation](https://github.com/garronej/tss-react#mui-integration).
You can also [submit an issue](https://github.com/garronej/tss-react/issues/new) for any bug or feature request, and [start a discussion](https://github.com/garronej/tss-react/discussions) if you need help.
:::
## Complete the migration
Once you migrate all of the styling, remove unnecessary `@mui/styles` by uninstalling the package.
With npm:
```bash
npm uninstall @mui/styles
```
With yarn:
```bash
yarn remove @mui/styles
```
:::warning
`@emotion/styled` is a peer dependency of `@mui/material`.
You must keep it in your dependencies even if you never explicitly use it.
:::