【问题标题】:How to use 'theme' and 'props' in makeStyles?如何在 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);

其中backgroundColorCSSProperties["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 答案以了解替代方法。

标签: reactjs material-ui


【解决方案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 变量是否被导入到组件中。

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

          【讨论】:

            猜你喜欢
            • 2021-08-19
            • 2021-09-30
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2019-10-13
            • 1970-01-01
            • 2021-09-02
            • 2020-07-22
            相关资源
            最近更新 更多