score:24
This answer was written prior to version 4.0 severely out of date!
Seriously, if you're styling a function component, use makeStyles
.
The answer from James Tan is the best answer for version 4.x
Anything below here is ancient:
When you're using withStyles
, you have access to the theme
, but not props
.
Please note that there is an open issue on Github requesting this feature and some of the comments may point you to an alternative solution that may interest you.
One way to change the background color of a card using props would be to set this property using inline styles. I've forked your original codesandbox with a few changes, you can view the modified version to see this in action.
Here's what I did:
- Render the component with a
backgroundColor
prop:
// in index.js
if (rootElement) {
render(<Demo backgroundColor="#f00" />, rootElement);
}
- Use this prop to apply an inline style to the card:
function SimpleCard(props) {
// in demo.js
const { classes, backgroundColor } = props;
const bull = <span className={classes.bullet}>•</span>;
return (
<div>
<Card className={classes.card} style={{ backgroundColor }}>
<CardContent>
// etc
Now the rendered Card component has a red (#F00) background
Take a look at the Overrides section of the documentation for other options.
score:1
Here's 2 full working examples of how to pass props to MUI v5 styles. Either using css or javascript object syntax.
With css syntax:
import { styled } from '@mui/system'
interface Props {
myColor: string
}
const MyComponent = ({ myColor }: Props) => {
const MyStyledComponent = styled('div')`
background-color: ${myColor};
.my-paragraph {
color: white;
}
`
return (
<MyStyledComponent >
<p className="my-paragraph">Hello there</p>
</MyStyledComponent >
)
}
export default MyComponent
Note that we define MyStyledComponent
within MyComponent
, making the scoped props available to use in the template string of the styled()
function.
Same thing with javascript object syntax:
import { styled } from '@mui/system'
const MyComponent = ({ className }: any) => {
return (
<div className={className}>
<p className="my-paragraph">Hello there</p>
</div>
)
}
interface Props {
myColor: string
}
const MyStyledComponent = styled(MyComponent)((props: Props) => ({
backgroundColor: props.myColor,
'.my-paragraph': { color: 'white' },
}))
export default MyStyledComponent
For this second example, please note how we pass the className
to the component we want to apply the styles to. The styled()
function will pass a className
prop with the styles you define. You typically want to apply that to your root element. In this case the div
.
Result:
I'm sure there's other variations of how to do this, but these two are easy to implement and understand.
You might need to memoize the calculated styles, and maybe not use this approach if your props changes a lot. I don't think it's very performant.
score:2
export const renderButton = (tag, method, color) => {
const OkButton = withStyles({
root: {
"color": `${color}`,
"filter": "opacity(0.5)",
"textShadow": "0 0 3px #24fda39a",
"backgroundColor": "none",
"borderRadius": "2px solid #24fda3c9",
"outline": "none",
"border": "2px solid #24fda3c9",
"&:hover": {
color: "#24fda3c9",
border: "2px solid #24fda3c9",
filter: "opacity(1)",
},
"&:active": {
outline: "none",
},
"&:focus": {
outline: "none",
},
},
})(Button);
return (
<OkButton tag={tag} color={color} fullWidth onClick={method}>
{tag}
</OkButton>
);
};
renderButton('Submit', toggleAlert, 'red')
score:2
Solution for TypeScript with Class Component:
type PropsBeforeStyle = {
propA: string;
propB: number;
}
const styles = (theme: Theme) => createStyles({
root: {
color: (props: PropsBeforeStyle) => {}
}
});
type Props = PropsBeforeStyle & WithStyles<typeof styles>;
class MyClassComponent extends Component<Props> {...}
export default withStyles(styles)(MyClassComponent);
score:2
Here's another way of dynamically passing props to hook's API in MUI v5
import React from "react";
import { makeStyles } from "@mui/styles";
import { Theme } from "@mui/material";
interface StyleProps {
height: number;
backgroundColor: string;
}
const useStyles = makeStyles<Theme>((theme) => ({
root: ({ height, backgroundColor }: StyleProps) => ({
background: backgroundColor,
height: height
})
}));
export default function Hook() {
const props = {
height: 58,
backgroundColor: "red"
};
const classes = useStyles(props);
return (
<button className={classes.root}>
another way of passing props to useStyle hooks
</button>
);
}
here's the codesandbox https://codesandbox.io/s/styles-with-props-forked-gx3bf?file=/demo.tsx:0-607
score:3
I spent a couple of hours trying to get withStyles to work with passing properties in Typescript. None of the solutions I found online worked with what I was trying to do, so I ended up knitting my own solution together, with snippets from here and there.
This should work if you have external components from, lets say Material UI, that you want to give a default style, but you also want to reuse it by passing different styling options to the component:
import * as React from 'react';
import { Theme, createStyles, makeStyles } from '@material-ui/core/styles';
import { TableCell, TableCellProps } from '@material-ui/core';
type Props = {
backgroundColor?: string
}
const useStyles = makeStyles<Theme, Props>(theme =>
createStyles({
head: {
backgroundColor: ({ backgroundColor }) => backgroundColor || theme.palette.common.black,
color: theme.palette.common.white,
fontSize: 13
},
body: {
fontSize: 12,
},
})
);
export function StyledTableCell(props: Props & Omit<TableCellProps, keyof Props>) {
const classes = useStyles(props);
return <TableCell classes={classes} {...props} />;
}
It may not be the perfect solution, but it seems to work. It's a real bugger that they haven't just amended withStyles to accept properties. It would make things a lot easier.
score:6
import React from "react";
import { makeStyles } from "@material-ui/styles";
import Button from "@material-ui/core/Button";
const useStyles = makeStyles({
root: {
background: props => props.color,
"&:hover": {
background: props => props.hover
}
}
});
export function MyButton(props) {
const classes = useStyles({color: 'red', hover: 'green'});
return <Button className={classes.root}>My Button</Button>;
}
score:6
@mui v5
You can use styled() utility (Make sure that you're importing the correct one) and shouldForwardProp
option.
In the following example SomeProps
passed to a div
component
import { styled } from '@mui/material'
interface SomeProps {
backgroundColor: 'red'|'blue',
width: number
}
const CustomDiv = styled('div', { shouldForwardProp: (prop) => prop !== 'someProps' })<{
someProps: SomeProps;
}>(({ theme, someProps }) => {
return ({
backgroundColor: someProps.backgroundColor,
width: `${someProps.width}em`,
margin:theme.spacing(1)
})
})
score:7
Was missing from this thread a props
use within withStyles
(and lead to think it wasn't supported)
But this worked for me (say for styling a MenuItem
):
const StyledMenuItem = withStyles((theme) => ({
root: {
'&:focus': {
backgroundColor: props => props.focusBackground,
'& .MuiListItemIcon-root, & .MuiListItemText-primary': {
color: props => props.focusColor,
},
},
},
}))(MenuItem);
And then use it as so:
<StyledMenuItem focusColor={'red'} focusBackground={'green'}... >...</StyledMenuItem>
score:28
In MUI v5, this is how you access the props when creating the style object using styled()
:
import { styled } from "@mui/material";
const StyledBox = styled(Box)(({ theme, myColor }) => ({
backgroundColor: myColor,
width: 30,
height: 30
}));
For folks who use typescript, you also need to add the prop type to the CreateStyledComponent
:
type DivProps = {
myColor: string;
};
const Div = styled(Box)<DivProps>(({ theme, myColor }) => ({
backgroundColor: myColor,
width: 30,
height: 30
}));
<StyledBox myColor="pink" />
If you want to use system props in your custom component like Box
and Typography
, you can use extendSxProp
like the example below:
import { unstable_extendSxProp as extendSxProp } from "@mui/system";
const StyledDiv = styled("div")({});
function DivWithSystemProps(inProps) {
const { sx } = extendSxProp(inProps);
return <StyledDiv sx={sx} />;
}
<DivWithSystemProps
bgcolor="green"
width={30}
height={30}
border="solid 1px red"
/>
Explanation
styled("div")()
: Add thesx
props to your custom componentextendSxProp(props)
: Gather the top level system props and put it inside thesx
property:
const props = { notSystemProps: true, color: 'green', bgcolor: 'red' };
const finalProps = extendSxProp(props);
// finalProps = {
// notSystemProps: true,
// sx: { color: 'green', bgcolor: 'red' }
// }
To use with typescript, you need to add the type for all system properties:
type DivSystemProps = SystemProps<Theme> & {
sx?: SxProps<Theme>;
};
function DivWithSystemProps(inProps: DivSystemProps) {
const { sx, ...other } = extendSxProp(inProps);
return <StyledDiv sx={sx} {...other} />;
}
score:35
Here's the official Material-UI demo.
And here's a very simple example. It uses syntax similar to Styled Components:
import React from "react";
import { makeStyles, Button } from "@material-ui/core";
const useStyles = makeStyles({
root: {
background: props => props.color,
"&:hover": {
background: props => props.hover
}
},
label: { fontFamily: props => props.font }
});
export function MyButton(props) {
const classes = useStyles(props);
return <Button className={classes.root} classes={{ label: classes.label }}>My Button</Button>;
}
// and the JSX...
<MyButton color="red" hover="blue" font="Comic Sans MS" />
This demo uses makeStyles
, but this feature is also available in styled
and withStyles
.
This was first introduced in @material-ui/styles on Nov 3, 2018 and was included in @material-ui/core starting with version 4.
score:52
Here the Typescript solution:
import React from 'react';
import { makeStyles } from '@material-ui/core/styles';
import Button from '@material-ui/core/Button';
import {Theme} from '@material-ui/core';
export interface StyleProps {
height: number;
}
const useStyles = makeStyles<Theme, StyleProps>(theme => ({
root: {
background: 'green',
height: ({height}) => height,
},
}));
export default function Hook() {
const props = {
height: 48
}
const classes = useStyles(props);
return <Button className={classes.root}>Styled with Hook API</Button>;
}
If you want to play with it, try it in this CodeSandbox
score:55
Solution for how to use both props and theme in material ui :
const useStyles = props => makeStyles( theme => ({
div: {
width: theme.spacing(props.units || 0)
}
}));
export default function ComponentExample({ children, ...props }){
const { div } = useStyles(props)();
return (
<div className={div}>{children}</div>
);
}
score:147
Deleted the old answer, because it's no reason for existence.
Here's what you want:
import React from 'react';
import { makeStyles } from '@material-ui/core';
const useStyles = makeStyles({
firstStyle: {
backgroundColor: props => props.backgroundColor,
},
secondStyle: {
color: props => props.color,
},
});
const MyComponent = ({children, ...props}) =>{
const { firstStyle, secondStyle } = useStyles(props);
return(
<div className={`${firstStyle} ${secondStyle}`}>
{children}
</div>
)
}
export default MyComponent;
Now you can use it like:
<MyComponent color="yellow" backgroundColor="purple">
Well done
</MyComponent>
Source: stackoverflow.com
Related Query
- Passing props to MUI styles
- MUI v5 passing props to CSS theme using styled()
- Passing props to MUI drawer
- Passing styles from parent to mui component in react
- Passing props and styles to functional component (React)
- Passing object as props to jsx
- Passing props to react-redux container component
- React: Passing down props to functional components
- How to extend styled component without passing props to underlying DOM element?
- React — Passing props with styled-components
- Passing useState as props in typescript
- React - change input defaultValue by passing props
- Passing a function with parameters through props on reactjs
- Passing props into external stylesheet in React Native?
- Passing multiple props to React component
- React: Passing Props to Descendants
- Customize MUI Table styles - last-child
- Passing props to React Router children routes
- Passing props to component in React Router 4
- Passing custom props to router component in react-router v4
- React - passing object through props
- React-Redux mapStateToProps vs passing down parent props
- React memo components and re-render when passing function as props
- Does passing an object via props to child react component, clone the original object or pass by reference?
- Styling react-router-dom Link using styled-components getting warning when passing props
- Reactjs passing methods as props to child
- Passing props to a react component wrapped in withRouter() function
- Connecting child components to store vs connecting parent component to store and passing down props
- Passing props to the makeStyle in TS
- Global Styles with React and MUI
More Query from same tag
- Pass environment variable from package.json to React app
- What is the best way to import SVG using React.JS
- pseudo styled component h2 not showing in html
- Basic React form submit refreshes entire page
- Is there any way to avoid loading npm packages on pageload of React application
- Why id and itemId never match in that react code?
- React cannot read an object inside array (state)
- Sending a React.FunctionComponent<React.SVGProps<SVGSVGElement>> as a prop to another component
- React router dom changes url, does not render component
- react-hooks: skip first run in useEffect
- How to toggle css class of a single element in a .map() function in React
- Resize/scale entire canvas with all objects in fabricjs without loss of quality
- React Redux Lifecycle Props
- How do I trigger a call to dispatch using React Hooks?
- get empty request while posting
- Render a list of objects on a table object using axios calls : Rendering logic
- React-JS change state of a component by pressing on button
- try to render todo item as <li>, but todo.name is undefined
- Parse Error: Adjacent JSX elements must be wrapped in an enclosing tag
- How do I controll return type of useState
- Onclick with Button in Material-Table
- React: SetState does not update visual component
- Visual Studio npm modules
- How can I pass my theme classes in my react function to stylize?
- How to test Websocket Client with Jest and react-testing-library
- How to create a Micro Frontend bundle with Webpack that shares libraries with the container application?
- Route not defined react router and spring boot server
- Why React hook useState don't increment index onClick?
- Extending a reducer to different pages with slightly different data
- How to update styles dynamically in JSX