Imagine a scenario where there is a component responsible for rendering a button with a red background and yellow text color. A Parent component utilizes this child component but specifies that it wants the background color to be green while keeping the text color as yellow.
withStyles
No issues when utilizing the traditional withStyles method.
import React from "react";
import { withStyles } from "@material-ui/core/styles";
import { Button } from "@material-ui/core";
const parentStyles = {
root: {
background: "green"
}
};
const childStyles = {
root: {
background: "red"
},
label: {
color: "yellow"
}
};
const ChildWithStyles = withStyles(childStyles)(({ classes }) => {
return <Button classes={classes}>Button in Child withStyles</Button>;
});
const ParentWithStyles = withStyles(parentStyles)(({ classes }) => {
return <ChildWithStyles classes={classes} />;
});
export default ParentWithStyles;
https://i.sstatic.net/UL3Dr.png
https://codesandbox.io/s/passing-classes-using-withstyles-w17xs?file=/demo.tsx
makeStyles/useStyles
Let's experiment with the makeStyles/useStyles approach and refer to the guide Overriding styles - classes prop on material-ui.com.
import React from "react";
import { makeStyles } from "@material-ui/styles";
import { Button } from "@material-ui/core";
const parentStyles = {
root: {
background: "green"
}
};
const childStyles = {
root: {
background: "red"
},
label: {
color: "yellow"
}
};
// The useStyles variant does NOT allow me to override classes
const useParentStyles = makeStyles(parentStyles);
const useChildStyles = makeStyles(childStyles);
const ChildUseStyles = ({ classes: classesOverride }) => {
const classes = useChildStyles({ classes: classesOverride });
return (
<>
<Button classes={classes}>Button1 in Child useStyles</Button>
<Button classes={classesOverride}>Button2 in Child useStyles</Button>
</>
);
};
const AnotherChildUseStyles = props => {
const classes = useChildStyles(props);
return (
<>
<Button classes={classes}>Button3 in Child useStyles</Button>
</>
);
};
const ParentUseStyles = () => {
const classes = useParentStyles();
return <>
<ChildUseStyles classes={classes} />
<AnotherChildUseStyles classes={classes} />
</>;
};
export default ParentUseStyles;
https://i.sstatic.net/OVkxQ.png
https://codesandbox.io/s/passing-classes-using-usestyles-6x5hf?file=/demo.tsx
It appears challenging to achieve the desired effect I had with withStyles using the classes overriding method (particularly making sense to me previously).
- What am I misunderstanding about passing classes for overriding purposes using useStyles?
- How should I approach it differently?
- If my current approach is incorrect, why is material-ui still issuing a warning when the parent contains styles not found in the child?
- Is there documentation available for migrating from the old withStyles approach to the new one?
By the way, I am aware of this solution, but it seems cumbersome when dealing with numerous overrides.
const useStyles = makeStyles({
root: {
backgroundColor: 'red',
color: props => props.color,
},
});
function MyComponent(props) {
const classes = useStyles(props);
return <div className={classes.root} />;
}