What is the benefit of using withStyles over makeStyles?
UPDATE This question/answer is geared towards v4 of Material-UI. I have added some v5 info/links at the end.
The Hook API (makeStyles/useStyles
) can only be used with function components.
The Higher-order component API (withStyles
) can be used with either class components or function components.
They both provide the same functionality and there is no difference in the styles
parameter for withStyles
and makeStyles
.
If you are using it with a function component, then I would recommend using the Hook API (makeStyles
). withStyles
has a little bit of extra overhead compared to makeStyles
(and internally delegates to makeStyles
).
If you are customizing the styles of a Material-UI component, using withStyles
is preferable to wrapping it with your own component solely for the purpose of calling makeStyles/useStyles
since then you would just be re-implementing withStyles
.
So wrapping a Material-UI component might look like the following example (from How to style Material-UI's tooltip?):
const BlueOnGreenTooltip = withStyles({
tooltip: {
color: "lightblue",
backgroundColor: "green"
}
})(Tooltip);
For v5 of Material-UI, styled
replaces withStyles
and makeStyles
. How to style Material-UI's tooltip? contains v5 examples. I also have further discussion of v5 styling options in Using conditional styles in Material-UI with styled vs JSS.
What is difference between withStyles and makeStyles from Material UI framework?
The main difference is that makeStyle/useStyle is being used at function components as a hook, and withStyles is an higher order component.
useStyle and withStyles provide the same functionality and take the same style object params.
you should use withStyles when you develop apps with React version that doens't support hooks yet, or when you style a class-based component.
Material-UI makeStyles vs withStyles generated class names
The second (optional) argument to makeStyles
is an object of options to control the behavior of makeStyles
. One of the options is a name which is then used as a prefix for the class names. withStyles
passes Component.displayName as the name
option. You can specify whatever name you want in order to control the class name prefix, for instance in my example below the class name ends up being Hello-root-1
.
import { makeStyles } from "@material-ui/core/styles";
const useStyles = makeStyles(
{
root: {
backgroundColor: "green"
}
},
{ name: "Hello" }
);
export default function App() {
const classes = useStyles();
return (
<div>
<h1 className={classes.root}>Hello CodeSandbox</h1>
</div>
);
}
Material-UI - Why should I use makeStyles instead of inline styles?
There are a few scenarios where using CSS classes (e.g. via makeStyles
or withStyles
) is necessary:
- If you want to use media queries in your CSS
- If you want to target pseudo-classes (e.g. :hover)
- If you are creating a reusable customization of one of the Material-UI components and want to customize some of the classes that are conditionally applied to the element based on props or some other context (e.g. if you want to customize the "error" look of an Input while leaving it up to the places where the custom component is used to specify the
error
prop either directly or via theFormControl
context)
As far as performance concerns, I would expect inline styles to be faster for most use cases. Whether the difference is enough to matter would depend on a lot of specifics regarding your particular application. The team I work with uses makeStyles
or withStyles
for most of our styling.
Inline styles can result in a lot of duplicated CSS in the DOM if a particular component is rendered many times within the document (e.g. list items, table cells, etc.). One nice thing about always using classes is that you can change the CSS for the class in the browser's developer tools and see that change applied throughout all its usages in the document.
Is there a performance difference between the sx prop and the makeStyles function in Material UI?
JSS is slightly faster than Emotion for static styles (i.e. styles that aren't dynamic based on props). JSS is much slower than Emotion for dynamic styles -- Emotion has similar performance for both static and dynamic styles.
You can find information about the performance difference for static styles between JSS and Emotion in the following issues:
- https://github.com/mui-org/material-ui/issues/22342#issuecomment-696553225
- https://github.com/mui-org/material-ui/pull/22173#issuecomment-673486269
JSS was about 10% faster than Emotion for static styles. For dynamic styles, JSS was 6 times slower than Emotion in one test the Material-UI team performed, and this is why JSS was eliminated from the list of possible styling engines for v5.
The documentation at https://next.material-ui.com/system/basics/#the-sx-prop contains the following performance information:
Benchmark case | Code snippet | Time normalized |
---|---|---|
a. Render 1,000 primitives | <div className="…"> | 100ms |
b. Render 1,000 components | <Div> | 120ms |
c. Render 1,000 styled components | <StyledDiv> | 160ms |
d. Render 1,000 Box | <Box sx={…}> | 370ms |
How to style components using makeStyles and still have lifecycle methods in Material UI?
What we ended up doing is stopped using the class components and created Functional Components, using useEffect()
from the Hooks API for lifecycle methods. This allows you to still use makeStyles()
with Lifecycle Methods without adding the complication of making Higher-Order Components. Which is much simpler.
Example:
import React, { useEffect, useState } from 'react';
import axios from 'axios';
import { Redirect } from 'react-router-dom';
import { Container, makeStyles } from '@material-ui/core';
import LogoButtonCard from '../molecules/Cards/LogoButtonCard';
const useStyles = makeStyles(theme => ({
root: {
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
margin: theme.spacing(1)
},
highlight: {
backgroundColor: 'red',
}
}));
// Highlight is a bool
const Welcome = ({highlight}) => {
const [userName, setUserName] = useState('');
const [isAuthenticated, setIsAuthenticated] = useState(true);
const classes = useStyles();
useEffect(() => {
axios.get('example.com/api/username/12')
.then(res => setUserName(res.userName));
}, []);
if (!isAuthenticated()) {
return <Redirect to="/" />;
}
return (
<Container maxWidth={false} className={highlight ? classes.highlight : classes.root}>
<LogoButtonCard
buttonText="Enter"
headerText={isAuthenticated && `Welcome, ${userName}`}
buttonAction={login}
/>
</Container>
);
}
}
export default Welcome;
Difference between @mui/material/styles and @mui/styles?
Normally in v4, you'd import the style API from @material-ui/core/styles
. This one uses JSS behind the scene:
import { makeStyles } from '@material-ui/core/styles';
In v5, they changed the brand name to MUI. As a result, the package name changed too:
import { makeStyles } from '@mui/material/styles';
But MUI v5 also drops the support for JSS (which makeStyles
/withStyles
are using), so they move those APIs to a legacy package called @mui/styles
. (They plan to remove this API in v6, but there are some pushback. See this issue for more info)
import { makeStyles } from '@mui/styles';
And encourage the users to adopt a newer styling solution (sx
, styled
) using emotion as a default style engine:
import { styled } from "@mui/material/styles";
So in summary, the difference between the @mui/material/styles
and @mui/styles
is that:
@mui/styles | @mui/material/styles |
---|---|
Doesn't come with a default theme, need createTheme / ThemeProvider | Come with a default material theme (as opposed to the other planned theme) |
Legacy styling package | Depends on the new @mui/system package |
Powered by JSS | Powered by emotion (as a default style engine) |
Has makeStyles /withStyles | Doesn't have makeStyles /withStyles , has styled instead |
Related Topics
Can CSS Identifiers Begin with Two Hyphens
Why Does the CSS3 Pseudo ::Selection Not Change the Color for All Parts
Limit the Width of a Column to the Width of a Particular Grid Item
Use Calc() Function in Makestyles
Continuously Adjust Element Size as Screen Size Changes
Less Mixin - Output Values Without Quotes
Vertical Align with Absolute Positioning
How to Change CSS Class for the Inputfield and Label When Validation Fails
Prevent a Pseudo Element from Triggering Hover
CSS Transform: Scale Does Not Change Dom Size
Does IE9 Not Support Display: Inline-Flex at All
Make Outer Div Be Automatically the Same Height as Its Floating Content
Div Height 100% and Expands to Fit Content
CSS How to Print a Table with Background Color (Without Print Settings Changes)