如何在 makeStyles 中使用“主题”和“props”?

IT技术 reactjs material-ui
2021-04-24 04:09:19

我如何编写makeStyles()以便它允许我同时使用主题变量和props?

我试过这个:

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带有类型的组件上的props在哪里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 版本的材料核心和样式

4个回答

测试:

"@material-ui/core": "^4.0.0-beta.1",
"@material-ui/styles": "^4.0.0-rc.0",

JavaScript 示例:

我的component.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
    )
}

我的component.styles.js

export const useStyles = makeStyles(theme => ({
    mySelector: props => ({
        display: 'block',
        width: props.width,
        height: props.height,
    }),
}));

typescript示例:

我的component.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
    )
}

我的component.interfaces.ts

export interface StyleProps {
    width: string;
    height: string;
}

export interface MyComponentProps {
}

我的component.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"

您需要将对象传递给useStyles而不是字符串。

所以而不是:

const classes = useStyles(backgroundColor);

你应该有:

const classes = useStyles(props);

或者

const classes = useStyles({backgroundColor});

然后您可以使用以下方法获得 backgroundColor:

color: theme.palette.getContrastText(props.backgroundColor).

这是一个工作示例:https : //codesandbox.io/s/o7xryjnmly

你可以这样做:(我不知道是否是最好的方法但有效......也可以访问主题ang globals provider(使用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 通过 params 获取主题,因此您可以为每个带有箭头函数的组件创建一个 style.js,并从可以访问主题提供程序的 makeStyles 调用。

我们通常有 2 种模式,您的prop变量是否导入到组件中。

  1. 如果你的prop变量是导入的,它是一个全局变量,所以它在 makeStyles() 中是有效的:
     import {prop} from ...
    
     const useStyles = makeStyles((theme) => ({
       className:{
          // use prop
       }
     })
    
     define component...
  1. 如果您的prop变量是在组件中定义的(例如状态),您有两种选择:
  • 您可以将prop变量传递给 makeStyles():

    const useStyles = makeStyles((theme,prop) => ({
      className:{
         // use prop
      }
    })
    
    define component...
  • 您可以使用箭头函数而无需向 makeStyles() 传递任何参数(主题除外):
    const useStyles = makeStyles((theme) => ({
      className:(prop)=>({
         //use prop
      })
    })

    define component...