Material UI: how do I use Theme values with withStyles? - reactjs

I am building a component with Material UI. I am using the default theme file (as per here https://material-ui.com/customization/default-theme/).
I know I can bring in certain values from the theme with makeStyles as such:
import { makeStyles, Theme } from '#material-ui/styles';
const useStyles = makeStyles((theme: Theme) => ({
something: {
color: theme.palette.common.black,
},
}));
That works fine.
But how do I use those same values with styled Material UI components? eg:
import withStyles from '#material-ui/core/styles';
const StyledBadge = withStyles({
badge: {
color: theme.palette.common.black,
},
})(Badge);
I tried replicating the above, eg:
const StyledBadge = withStyles((theme: Theme) => ({
but this doesn't work.
Would anyone know the correct way of doing this?

I tried creating Component withStyles as below and it is working perfectly.
import { withStyles } from "#material-ui/core";
export const ExpansionPanelDetails = withStyles(theme => ({
root: {
padding: theme.spacing(1),
},
}))(MuiExpansionPanelDetails);

Related

I can't change the global background material ui

the material ui libraries have a white global background by default at startup, I tried to change it to red, but it doesn't work. How can it be changed? the default is a white background, I want to make a different color
MuiDivider: {
styleOverrides: {
root: {
backgroundColor:"#cc5a5a",
},
},
},
I think you should import 'makeStyles' to be able to change the background. You can try this one:
import { makeStyles } from "#material-ui/core/styles";
const useStyles = makeStyles((theme) => ({
root: {
borderColor: "#cc5a5a",
backgroundColor:"#cc5a5a",
}
}));
export default function Sample() {
const classes = useStyles();
return (
<div className={classes.root}>...</div>
)
}
Also do try to do some research in the future before posting a question here.

How can i get the context of the MUI theme?

This is how you create a theme and propagate it using MUI.
import { ThemeProvider } from "#mui/material";
const myTheme = createTheme({
backgroundColor: {
primary: "#f9f9fb",
secondary: "#ededf3",
tertiary: "#cbcbdc",
},
})
const Index: FC = () => {
<ThemeProvider theme={theme}>
<App />
</ThemeProvider>
};
Now, for some reason, I need to get the context of the MUI theme in my app.
I've search everywhere but it seems that they do not expose the context anywhere. I found 3 contexts in private-theming, styled-engine and styled-engine-sc but none of them worked.
How can I do that ?
The way you create the theme it wrong should be like following:
const theme = createTheme({
palette: {
primary: {
main: red[500],
},
},
});
with the property palette.
and the way to get values you could use the hook useTheme .
first import
import { useTheme } from "#mui/material";
and inside your components you can use the palette you set to your theme like:
const { palette } = useTheme();
MUI uses the context provided by the styled engine:
import { ThemeContext } from '#mui/styled-engine';
It can also be imported directly from your engine of choice (emotion in the example below):
import { ThemeContext } from '#emotion/react';

React jss overrides parent styles and retains child style

in using the jss lib in react with a custom theme that merges two themes together for use. Previously there was no problems but to type it correctly and create an ease of development, it was modified a bit of how the createUseStyles works. Here is an example of the usage before the change:
import { cn, createUseStyles, useTheme } from "#styling";
const useStyles = createUseStyles({
container: {
width: "500px",
height: "100px",
}
});
const Child = ({extraStyles}:{extraStyles:string[]}) => {
const theme = useTheme();
const styles = useStyles({theme});
return (
<div className={cn(styles.container, ...extraStyles)}>
</div>
)
}
// parent
import { cn, createUseStyles, useTheme } from "#styling";
import Child from "#child";
const useStyles = createUseStyles({
large: {
width: "999px",
height: "999px",
}
});
const Parent = () => {
const theme = useTheme();
const styles = useStyles({theme});
return (
<Child extraStyles={[styles.large]}/>
)
}
where cn just combined the classes together. This would result in a stylesheet where the parents styles would override the childs, allowing for flexibility.
After some necessary modification the createUseStyles is typed and generated within the styling. It looks something like this:
//styling
import {
createUseStyles as createStyles,
useTheme,
ThemeProvider,
Styles,
} from "react-jss";
const createUseStyles = (styles) => {
return (props) => {
const tempTheme = useTheme();
const temp = createStyles(styles);
return temp({ ...props, theme: tempTheme });
};
};
export { ThemeProvider, createUseStyles };
I have excluded the extra typing, but it was essentially to save the need to typescript createUseStyles and the usage of useTheme every single time within a component.
...But in doing so & in usage the exact same example as provided above with this new createUseStyle, the child injects it's style above the parents and doesn't pull in the props styling. Using !important on every single prop style is extremely tedious.
I'm confused why just pulling useTheme outside would break the injection structure (assuming that is the cause of this problem)?
Possible, you can add index for createUseStyles to set order of injection, something like this:
// Child
const useStyles = createUseStyles({
container: {
width: "500px",
height: "100px",
}
}, { index: 2 });
// Parent
const useStyles = createUseStyles({
large: {
width: "999px",
height: "999px",
}
}, { index: 1 });
I don't know how it works, if you need to add into every componente style or in entire stylesheet. The official documentation of React JSS isn't clear but it has in JSS API.

material ui withStyles and WithTheme - How to access theme

const MySlider = withStyles({
root: {
color: theme => theme.palette.primary.main
}
}, {withTheme: true})(Slider);
I did expect the withTheme option would make the theme accessible inside withStyles. If so then how? because theme is not defined and its also not found in props ?
Any idea
withStyles function can accept a callback instead of an object giving you the access to the theme object like this
const NewButton = withStyles((theme) => {
root: {
color: theme.palette.primary
}
}, { withTheme: true })(Button);

Proper way to use Material UI in reactjs project

I've recently started using Material UI and I'm not sure what is the proper way to use it. There are some times when I want to customize the styles of the Material UIcomponents. But for that I have to work in the ".js" file, which I think isn't appropriate.
Is there a way where one can store multiple custom styles/components of Material UI components in a different file and then import the styles/components from there?
Thanks!
There is no problem in separating the styles from the components.
I for one even import the makeStyles hook inside the styles.js.
// styles.js
import { makeStyles } from '#material-ui/core/styles';
const styles = makeStyles(theme => ({
main: {
padding: theme.spacing(2),
},
}));
export default styles;
You can import the useStyles in the component if you like that better
// Component.jsx
import React from 'react';
import styles from './styles';
const Component = () => {
const classes = styles();
return (
<WhatEverComponent classsName={classes.main}/>
);
}
LE: makeStyles in Component
// styles.js
const styles = theme => ({
main: {
padding: theme.spacing(2),
},
});
export default styles;
// Component.jsx
import React from 'react';
import { makeStyles } from '#material-ui/core/styles';
import stylesObj from './styles';
const styles = makeStyles(stylesObj);
const Component = () => {
const classes = styles();
return (
<WhatEverComponent classsName={classes.main}/>
);
}
I've made also a sandbox here. You can check how both work.
I would suggest to use the first variant.

Resources