如何在 makeStyles 中使用“主题”和“道具”?
Posted
技术标签:
【中文标题】如何在 makeStyles 中使用“主题”和“道具”?【英文标题】:How to use 'theme' and 'props' in makeStyles? 【发布时间】:2019-09-30 08:26:47 【问题描述】:如何编写makeStyles()
以便它允许我同时使用主题变量和道具?
我试过了:
const useStyles = makeStyles(theme => (
appbar: props => (
boxShadow: "none",
background: "transparent",
marginTop: theme.spacing(2),
marginBottom: theme.spacing(2),
color: theme.palette.getContrastText(props)
),
));
并在组件中调用它:
const classes = useStyles(backgroundColor);
其中backgroundColor
是CSSProperties["backgroundColor"]
类型的组件上的道具
但我得到了错误:
TypeError: Cannot read property 'rules' of undefined
at RuleList.onUpdate (C:\Users\...\node_modules\jss\dist\jss.cjs.js:944:14)
at RuleList.update (C:\Users\...\node_modules\jss\dist\jss.cjs.js:923:12)
at StyleSheet.update (C:\Users\...\node_modules\jss\dist\jss.cjs.js:1178:39)
at attach (C:\Users\...\node_modules\@material-ui\styles\makeStyles\makeStyles.js:141:18)
at C:\Users\...\node_modules\@material-ui\styles\makeStyles\makeStyles.js:262:7
at useSynchronousEffect (C:\Users\...\node_modules\@material-ui\styles\makeStyles\makeStyles.js:207:14)
at C:\Users\...\node_modules\@material-ui\styles\makeStyles\makeStyles.js:254:5
at Layout (C:\Users\...\.next\server\static\development\pages\index.js:1698:17)
at processChild (C:\Users\...\node_modules\react-dom\cjs\react-dom-server.node.development.js:2888:14)
at resolve (C:\Users\...\node_modules\react-dom\cjs\react-dom-server.node.development.js:2812:5)
at ReactDOMServerRenderer.render (C:\Users\...\node_modules\react-dom\cjs\react-dom-server.node.development.js:3202:22)
at ReactDOMServerRenderer.read (C:\Users\...\node_modules\react-dom\cjs\react-dom-server.node.development.js:3161:29)
at renderToString (C:\Users\...\node_modules\react-dom\cjs\react-dom-server.node.development.js:3646:27)
at render (C:\Users\...\node_modules\next-server\dist\server\render.js:86:16)
at renderPage (C:\Users\...\node_modules\next-server\dist\server\render.js:211:20)
at ctx.renderPage (C:\Users\...\.next\server\static\development\pages\_document.js:2404:22)
100 | handleSignUpClick,
101 | backgroundColor
102 | ) =>
> 103 | const classes = useStyles(backgroundColor);
104 | return (
105 | <AppBar className=classes.appbar>
106 | <Container maxWidth="lg">
编辑:我使用的是 4.0.0-beta.1 版本的材料核心和样式
【问题讨论】:
我可能会迟到。但是,有一个非常酷的视频,它会引导您了解将主题传递给 makeStyles 的基础知识:youtu.be/… 如果您使用的是 MUI v5,请参阅this 答案以了解替代方法。 【参考方案1】:你可以这样做:
import makeStyles, createStyles, Theme from "@material-ui/core/styles";
...
...
const classes = useStyles();
...
...
const useStyles = makeStyles((theme: Theme) =>
createStyles(
root: propName => (
border: "none",
boxShadow: "none",
cursor: propName ? "pointer" : "auto",
width: "100%",
backgroundColor: "#fff",
padding: "15px 15px"
),
updated:
marginTop: 12,
fontWeight: 400,
color: "#939393"
)
);
您可以在要设置样式的元素中使用道具名称,方法是将其设置为返回样式的箭头函数。此外,您还可以在 createStyles 钩子中设置其他元素的样式。这花了我一些时间,我希望任何人都觉得它有用。 ✨?
【讨论】:
【参考方案2】:测试:
"@material-ui/core": "^4.0.0-beta.1",
"@material-ui/styles": "^4.0.0-rc.0",
javascript 示例:
我的组件.js
import React from 'react';
import makeStyles from '@material-ui/styles';
import useStyles from './my-component.styles.js';
const myComponent = (props) =>
const styleProps = width: '100px', height: '100px' ;
const classes = useStyles(styleProps);
return (
<div className=classes.mySelector></div> // with 100px and height 100px will be applied
)
我的组件.styles.js
export const useStyles = makeStyles(theme => (
mySelector: props => (
display: 'block',
width: props.width,
height: props.height,
),
));
TypeScript 示例:
我的组件.ts
import React, FC from 'react';
import makeStyles from '@material-ui/styles';
import useStyles from './my-component.styles.ts';
import MyComponentProps, StylesProps from './my-component.interfaces.ts';
const myComponent: FC<MyComponentProps> = (props) =>
const styleProps: StylesProps = width: '100px', height: '100px' ;
const classes = useStyles(styleProps);
return (
<div className=classes.mySelector></div> // with 100px and height 100px will be applied
)
我的组件.interfaces.ts
export interface StyleProps
width: string;
height: string;
export interface MyComponentProps
我的组件.styles.ts
import Theme from '@material-ui/core';
import makeStyles from '@material-ui/styles';
import StyleProps from './my-components.interfaces.ts';
export const useStyles = makeStyles<Theme, StyleProps>((theme: Theme) => (
mySelector: props => ( // props = width: string; height: string
display: 'block',
width: props.width,
height: props.height,
),
));
更新
重新测试
"@material-ui/core": "^4.12.X"
【讨论】:
@SaadKhan,你能告诉我你用的是哪个版本的@material-ui
吗?我想更新 Tested with part。
"@material-ui/core": "^4.8.3" 希望对您有所帮助
完全帮助我。谢谢! M-UI:4.12.x【参考方案3】:
这是一个示例,说明如何在 makeStyles() 中仅使用 props 或 props 和主题,就像 styled-components 一样
component.js
import tableCellStyling from './component.styled.js';
const RenderRow = (props) =>
const noPaddingTopBottom = tableCellStyling(props);
return(
<StyledTableRow>
data.map( (row,i) => (
<StyledTableCell className=noPaddingTopBottom>
row.data
</StyledTableCell>
)
</StyledTableRow>
)
;
假设我的由 RenderRow 组件传递给 tableCellStyling 的 props 对象中有 color: 'grey', thinRow: true
component.styled.js
import makeStyles from '@material-ui/core/styles';
export const tableCellStyling = makeStyles(theme => (
noPaddingTopBottom:
borderBottom: ( color ) => color ? `2px solid $color` : '2px solid red',
paddingBottom: props => props.hasActions && 0,
paddingTop: props => props.hasActions && 0,
backgroundColor: theme.palette.common.white,
,
));
【讨论】:
【参考方案4】:我们一般有 2 种模式,你的 prop 变量是否被导入到组件中。
-
如果你的prop变量是导入的,是全局变量,所以在makeStyles()中有效:
import prop from ...
const useStyles = makeStyles((theme) => (
className:
// use prop
)
define component...
- 如果您的 prop 变量在组件中定义(例如状态),您有 2 个选择:i>
const useStyles = makeStyles((theme,prop) => (
className:
// use prop
)
define component...
您可以在不向 makeStyles() 传递任何参数(主题除外)的情况下使用箭头函数:
const useStyles = makeStyles((theme) => (
className:(prop)=>(
//use prop
)
)
define component...
【讨论】:
【参考方案5】:您可以这样做:(我不知道是否是最好的方法,但可行...也可以访问主题 ang globals 提供程序(使用 themeProvider))
import makeStyles from '@material-ui/core/styles'
import styles from './styles';
const useStyles = makeStyles(theme => (styles(theme))); // here call styles function imported from styles.js
const SideNav = (drawerState, toggleDrawer) =>
const classes = useStyles();
return (
<Box className=classes.root>
<Drawer className="drawer" anchor="left" open=drawerState onClose=() => toggleDrawer(false)>
<NavList></NavList>
</Drawer>
</Box>
);
export default SideNav;
在styles.js中
const styles = (theme) =>
return (
root:
'& .drawer':
backgroundColor:'red'
);
export default styles;
makeStyles 通过参数获取主题 所以你可以为每个内部带有箭头函数的组件创建一个styles.js 从可以访问主题提供程序的 makeStyles 调用。
【讨论】:
【参考方案6】:您需要将对象传递给useStyles
,而不是字符串。
所以而不是:
const classes = useStyles(backgroundColor);
你应该有:
const classes = useStyles(props);
或
const classes = useStyles(backgroundColor);
然后你可以使用:
color: theme.palette.getContrastText(props.backgroundColor)
.
这是一个工作示例: https://codesandbox.io/s/o7xryjnmly
【讨论】:
以上是关于如何在 makeStyles 中使用“主题”和“道具”?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Reactjs Material UI 上使用 CSS @media 响应 makeStyles?
Material-UI Typescript 如何在组件类中从 makeStyle() 创建样式实例